2022-02-10 22:06:57 +00:00
|
|
|
//go:build !solution
|
2020-03-07 19:14:49 +00:00
|
|
|
|
|
|
|
package retryupdate
|
|
|
|
|
2024-06-07 01:08:48 +00:00
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/gofrs/uuid"
|
|
|
|
"gitlab.com/slon/shad-go/retryupdate/kvapi"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
authError *kvapi.AuthError
|
|
|
|
conflictError *kvapi.ConflictError
|
|
|
|
)
|
2020-03-07 19:14:49 +00:00
|
|
|
|
|
|
|
func UpdateValue(c kvapi.Client, key string, updateFn func(oldValue *string) (newValue string, err error)) error {
|
2024-06-07 01:08:48 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
2020-03-07 19:14:49 +00:00
|
|
|
}
|