//go:build !solution package retryupdate import ( "errors" "fmt" "github.com/gofrs/uuid" "gitlab.com/slon/shad-go/retryupdate/kvapi" ) var ( authError *kvapi.AuthError conflictError *kvapi.ConflictError ) func UpdateValue(c kvapi.Client, key string, updateFn func(oldValue *string) (newValue string, err error)) error { newVersion := uuid.Must(uuid.NewV4()) get: for { old, err := c.Get(&kvapi.GetRequest{Key: key}) var value *string oldUuid := uuid.Nil if err != nil { switch { case errors.As(err, &authError): return err case !errors.Is(err, kvapi.ErrKeyNotFound): continue } } else { value = &old.Value oldUuid = old.Version } for { new, err := updateFn(value) if err != nil { return err } _, err = c.Set(&kvapi.SetRequest{ Key: key, Value: new, OldVersion: oldUuid, NewVersion: newVersion, }) if err != nil { fmt.Println(err) switch { case errors.As(err, &conflictError): if conflictError.ExpectedVersion == newVersion { return nil } continue get case errors.Is(err, kvapi.ErrKeyNotFound): value = nil oldUuid = uuid.Nil continue case errors.As(err, &authError): return err default: continue } } return nil } } }