From 398f5ba442b8f9785b7a1615d72fc44e93da96f7 Mon Sep 17 00:00:00 2001 From: erius Date: Fri, 7 Jun 2024 04:08:48 +0300 Subject: [PATCH] Implemented retryupdate --- retryupdate/update.go | 63 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/retryupdate/update.go b/retryupdate/update.go index a404f18..8b5e4b3 100644 --- a/retryupdate/update.go +++ b/retryupdate/update.go @@ -2,8 +2,67 @@ package retryupdate -import "gitlab.com/slon/shad-go/retryupdate/kvapi" +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 { - panic("implement me") + 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 + } + } }