From c89770a47398058f6ea59f54e2065d7dcdaa7beb Mon Sep 17 00:00:00 2001 From: mikeb26 <83850730+mikeb26@users.noreply.github.com> Date: Wed, 28 Sep 2022 16:47:33 +0000 Subject: [PATCH] Add SaveStateWithETag() convenience function (#321) In the state API there's an existing DeleteStateWithETag() convenience function but there does not appear to be an equivalent SaveStateWithETag(). This commit adds SetStateWithETag() so that consumers of the SDK don't have to employ the more verbose SaveBulkState() when they only need to update a singular item. Client code updating a single item with an etag prior to this commit looks like: -- item := &dapr.SetStateItem{ Etag: &dapr.ETag{ Value: "deadbeef", }, Key: "order_1", Value: []byte(data), } err := client.SaveBulkState(ctx, store, item) -- Client code after this commit can reduce to: -- err := client.SaveStateWithEtag(ctx, store, "order_1", []byte(data), "deadbeef") -- Signed-off-by: Mike Brown Signed-off-by: Mike Brown --- client/client.go | 3 +++ client/state.go | 8 ++++++++ client/state_test.go | 20 +++----------------- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/client/client.go b/client/client.go index cab3627..71bfdcd 100644 --- a/client/client.go +++ b/client/client.go @@ -90,6 +90,9 @@ type Client interface { // SaveState saves the raw data into store using default state options. SaveState(ctx context.Context, storeName, key string, data []byte, meta map[string]string, so ...StateOption) error + // SaveState saves the raw data into store using provided state options and etag. + SaveStateWithETag(ctx context.Context, storeName, key string, data []byte, etag string, meta map[string]string, so ...StateOption) error + // SaveBulkState saves multiple state item to store with specified options. SaveBulkState(ctx context.Context, storeName string, items ...*SetStateItem) error diff --git a/client/state.go b/client/state.go index 5bd2ad3..937140d 100644 --- a/client/state.go +++ b/client/state.go @@ -276,6 +276,11 @@ func (c *GRPCClient) ExecuteStateTransaction(ctx context.Context, storeName stri // SaveState saves the raw data into store, default options: strong, last-write. func (c *GRPCClient) SaveState(ctx context.Context, storeName, key string, data []byte, meta map[string]string, so ...StateOption) error { + return c.SaveStateWithETag(ctx, storeName, key, data, "", meta, so...) +} + +// SaveStateWithETag saves the raw data into store using provided state options and etag. +func (c *GRPCClient) SaveStateWithETag(ctx context.Context, storeName, key string, data []byte, etag string, meta map[string]string, so ...StateOption) error { stateOptions := new(StateOptions) for _, o := range so { o(stateOptions) @@ -289,6 +294,9 @@ func (c *GRPCClient) SaveState(ctx context.Context, storeName, key string, data Metadata: meta, Options: stateOptions, } + if etag != "" { + item.Etag = &ETag{Value: etag} + } return c.SaveBulkState(ctx, storeName, item) } diff --git a/client/state_test.go b/client/state_test.go index d145c36..34479a0 100644 --- a/client/state_test.go +++ b/client/state_test.go @@ -86,14 +86,7 @@ func TestSaveState(t *testing.T) { }) t.Run("save data with version", func(t *testing.T) { - item := &SetStateItem{ - Etag: &ETag{ - Value: "1", - }, - Key: key, - Value: []byte(data), - } - err := testClient.SaveBulkState(ctx, store, item) + err := testClient.SaveStateWithETag(ctx, store, key, []byte(data), "1", nil) assert.Nil(t, err) }) @@ -147,15 +140,8 @@ func TestDeleteState(t *testing.T) { }) t.Run("save data again with etag, meta", func(t *testing.T) { - err := testClient.SaveBulkState(ctx, store, &SetStateItem{ - Key: key, - Value: []byte(data), - Etag: &ETag{ - Value: "1", - }, - Metadata: map[string]string{"meta1": "value1"}, - Options: &StateOptions{Concurrency: StateConcurrencyFirstWrite, Consistency: StateConsistencyEventual}, - }) + meta := map[string]string{"meta1": "value1"} + err := testClient.SaveStateWithETag(ctx, store, key, []byte(data), "1", meta, WithConsistency(StateConsistencyEventual), WithConcurrency(StateConcurrencyFirstWrite)) assert.Nil(t, err) }) t.Run("confirm data saved", func(t *testing.T) {