shad-go/retryupdate/update.go
2024-06-07 04:08:48 +03:00

68 lines
1.3 KiB
Go

//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
}
}
}