From e2ddc9f96d4acd38434d5ba3544fc5e205dd5c29 Mon Sep 17 00:00:00 2001 From: Pruthvidhar R Dhodda <60198385+pruthvidhodda@users.noreply.github.com> Date: Mon, 14 Sep 2020 16:32:50 -0700 Subject: [PATCH] Add metadata support for state API's (#336) * Add metadata support for state API's * Remove .vscode files --- pom.xml | 2 +- .../java/io/dapr/client/DaprClientGrpc.java | 6 ++- .../java/io/dapr/client/DaprClientHttp.java | 4 ++ .../client/domain/DeleteStateRequest.java | 13 +++++ .../domain/DeleteStateRequestBuilder.java | 10 ++++ .../dapr/client/domain/GetStateRequest.java | 14 +++++ .../client/domain/GetStateRequestBuilder.java | 10 ++++ .../io/dapr/client/DaprClientGrpcTest.java | 53 +++++++++++++++++++ .../io/dapr/client/DaprClientHttpTest.java | 36 +++++++++++++ 9 files changed, 145 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index bb08e284c..94bbd65e1 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ 1.25.0 3.11.0 3.10.0 - https://raw.githubusercontent.com/dapr/dapr/13ee06cb55f1da9b7f823c42672e689a3cbb9df3/dapr/proto + https://raw.githubusercontent.com/dapr/dapr/2f32759fb9798d79b6d3fa92b1d972b07a62b6e8/dapr/proto 1.6.2 3.1.1 1.8 diff --git a/sdk/src/main/java/io/dapr/client/DaprClientGrpc.java b/sdk/src/main/java/io/dapr/client/DaprClientGrpc.java index d78bc4528..39ecd46ad 100644 --- a/sdk/src/main/java/io/dapr/client/DaprClientGrpc.java +++ b/sdk/src/main/java/io/dapr/client/DaprClientGrpc.java @@ -231,7 +231,8 @@ public class DaprClientGrpc extends AbstractDaprClient { } DaprProtos.GetStateRequest.Builder builder = DaprProtos.GetStateRequest.newBuilder() .setStoreName(stateStoreName) - .setKey(key); + .setKey(key) + .putAllMetadata(request.getMetadata()); if (options != null && options.getConsistency() != null) { builder.setConsistency(getGrpcStateConsistency(options)); } @@ -358,7 +359,8 @@ public class DaprClientGrpc extends AbstractDaprClient { } DaprProtos.DeleteStateRequest.Builder builder = DaprProtos.DeleteStateRequest.newBuilder() .setStoreName(stateStoreName) - .setKey(key); + .setKey(key) + .putAllMetadata(request.getMetadata()); if (etag != null) { builder.setEtag(etag); } diff --git a/sdk/src/main/java/io/dapr/client/DaprClientHttp.java b/sdk/src/main/java/io/dapr/client/DaprClientHttp.java index 7fe56bc3d..2c0cbc5a0 100644 --- a/sdk/src/main/java/io/dapr/client/DaprClientHttp.java +++ b/sdk/src/main/java/io/dapr/client/DaprClientHttp.java @@ -289,6 +289,8 @@ public class DaprClientHttp extends AbstractDaprClient { .map(o -> o.getStateOptionsAsMap()) .orElse(new HashMap<>()); + request.getMetadata().forEach(urlParameters::put); + return this.client .invokeApi(DaprHttp.HttpMethods.GET.name(), url.toString(), urlParameters, headers, context) .flatMap(s -> { @@ -380,6 +382,8 @@ public class DaprClientHttp extends AbstractDaprClient { .map(stateOptions -> stateOptions.getStateOptionsAsMap()) .orElse(new HashMap<>()); + request.getMetadata().forEach(urlParameters::put); + return this.client.invokeApi( DaprHttp.HttpMethods.DELETE.name(), url, urlParameters, headers, context) .thenReturn(new Response<>(context, null)); diff --git a/sdk/src/main/java/io/dapr/client/domain/DeleteStateRequest.java b/sdk/src/main/java/io/dapr/client/domain/DeleteStateRequest.java index b08aed65f..002694943 100644 --- a/sdk/src/main/java/io/dapr/client/domain/DeleteStateRequest.java +++ b/sdk/src/main/java/io/dapr/client/domain/DeleteStateRequest.java @@ -7,6 +7,9 @@ package io.dapr.client.domain; import io.grpc.Context; +import java.util.Collections; +import java.util.Map; + /** * A request to delete a state by key. */ @@ -16,6 +19,8 @@ public class DeleteStateRequest { private String key; + private Map metadata; + private String etag; private StateOptions stateOptions; @@ -61,4 +66,12 @@ public class DeleteStateRequest { void setContext(Context context) { this.context = context; } + + public Map getMetadata() { + return metadata; + } + + void setMetadata(Map metadata) { + this.metadata = metadata == null ? Collections.emptyMap() : metadata; + } } diff --git a/sdk/src/main/java/io/dapr/client/domain/DeleteStateRequestBuilder.java b/sdk/src/main/java/io/dapr/client/domain/DeleteStateRequestBuilder.java index a964462f5..606befdd2 100644 --- a/sdk/src/main/java/io/dapr/client/domain/DeleteStateRequestBuilder.java +++ b/sdk/src/main/java/io/dapr/client/domain/DeleteStateRequestBuilder.java @@ -6,6 +6,8 @@ package io.dapr.client.domain; import io.grpc.Context; +import java.util.Collections; +import java.util.Map; /** * Builds a request to delete a state by key. @@ -16,6 +18,8 @@ public class DeleteStateRequestBuilder { private final String key; + private Map metadata; + private String etag; private StateOptions stateOptions; @@ -27,6 +31,11 @@ public class DeleteStateRequestBuilder { this.key = key; } + public DeleteStateRequestBuilder withMetadata(Map metadata) { + this.metadata = metadata == null ? null : Collections.unmodifiableMap(metadata); + return this; + } + public DeleteStateRequestBuilder withEtag(String etag) { this.etag = etag; return this; @@ -50,6 +59,7 @@ public class DeleteStateRequestBuilder { DeleteStateRequest request = new DeleteStateRequest(); request.setStateStoreName(this.stateStoreName); request.setKey(this.key); + request.setMetadata(metadata); request.setEtag(this.etag); request.setStateOptions(this.stateOptions); request.setContext(this.context); diff --git a/sdk/src/main/java/io/dapr/client/domain/GetStateRequest.java b/sdk/src/main/java/io/dapr/client/domain/GetStateRequest.java index 59303e82c..996d6eb58 100644 --- a/sdk/src/main/java/io/dapr/client/domain/GetStateRequest.java +++ b/sdk/src/main/java/io/dapr/client/domain/GetStateRequest.java @@ -7,6 +7,10 @@ package io.dapr.client.domain; import io.grpc.Context; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + /** * A request to get a state by key. */ @@ -16,6 +20,8 @@ public class GetStateRequest { private String key; + private Map metadata; + private String etag; private StateOptions stateOptions; @@ -61,4 +67,12 @@ public class GetStateRequest { void setContext(Context context) { this.context = context; } + + public Map getMetadata() { + return metadata; + } + + void setMetadata(Map metadata) { + this.metadata = metadata == null ? Collections.emptyMap() : metadata; + } } diff --git a/sdk/src/main/java/io/dapr/client/domain/GetStateRequestBuilder.java b/sdk/src/main/java/io/dapr/client/domain/GetStateRequestBuilder.java index 0db8e6275..efe5e4bb3 100644 --- a/sdk/src/main/java/io/dapr/client/domain/GetStateRequestBuilder.java +++ b/sdk/src/main/java/io/dapr/client/domain/GetStateRequestBuilder.java @@ -6,6 +6,8 @@ package io.dapr.client.domain; import io.grpc.Context; +import java.util.Collections; +import java.util.Map; /** * Builds a request to publish an event. @@ -16,6 +18,8 @@ public class GetStateRequestBuilder { private final String key; + private Map metadata; + private String etag; private StateOptions stateOptions; @@ -27,6 +31,11 @@ public class GetStateRequestBuilder { this.key = key; } + public GetStateRequestBuilder withMetadata(Map metadata) { + this.metadata = metadata == null ? null : Collections.unmodifiableMap(metadata); + return this; + } + public GetStateRequestBuilder withEtag(String etag) { this.etag = etag; return this; @@ -50,6 +59,7 @@ public class GetStateRequestBuilder { GetStateRequest request = new GetStateRequest(); request.setStateStoreName(this.stateStoreName); request.setKey(this.key); + request.setMetadata(this.metadata); request.setEtag(this.etag); request.setStateOptions(this.stateOptions); request.setContext(this.context); diff --git a/sdk/src/test/java/io/dapr/client/DaprClientGrpcTest.java b/sdk/src/test/java/io/dapr/client/DaprClientGrpcTest.java index 4415f20dc..b23b27fe1 100644 --- a/sdk/src/test/java/io/dapr/client/DaprClientGrpcTest.java +++ b/sdk/src/test/java/io/dapr/client/DaprClientGrpcTest.java @@ -10,7 +10,13 @@ import com.google.common.util.concurrent.SettableFuture; import com.google.protobuf.Any; import com.google.protobuf.ByteString; import com.google.protobuf.Empty; + +import io.dapr.client.domain.DeleteStateRequest; +import io.dapr.client.domain.DeleteStateRequestBuilder; +import io.dapr.client.domain.GetStateRequest; +import io.dapr.client.domain.GetStateRequestBuilder; import io.dapr.client.domain.HttpExtension; +import io.dapr.client.domain.Response; import io.dapr.client.domain.State; import io.dapr.client.domain.StateOptions; import io.dapr.serializer.DefaultObjectSerializer; @@ -699,6 +705,32 @@ public class DaprClientGrpcTest { assertEquals(expectedState, result.block()); } + @Test + public void getStateObjectValueWithMetadataTest() throws IOException { + String etag = "ETag1"; + String key = "key1"; + MyObject expectedValue = new MyObject(1, "The Value"); + StateOptions options = buildStateOptions(StateOptions.Consistency.STRONG, StateOptions.Concurrency.FIRST_WRITE); + Map metadata = new HashMap(); + metadata.put("key_1", "val_1"); + State expectedState = buildStateKey(expectedValue, key, etag, options); + DaprProtos.GetStateResponse responseEnvelope = DaprProtos.GetStateResponse.newBuilder() + .setData(serialize(expectedValue)) + .setEtag(etag) + .build(); + GetStateRequestBuilder builder = new GetStateRequestBuilder(STATE_STORE_NAME, key); + builder.withMetadata(metadata).withEtag(etag).withStateOptions(options); + GetStateRequest request = builder.build(); + SettableFuture settableFuture = SettableFuture.create(); + MockCallback callback = new MockCallback<>(responseEnvelope); + addCallback(settableFuture, callback, directExecutor()); + when(client.getState(any(io.dapr.v1.DaprProtos.GetStateRequest.class))) + .thenReturn(settableFuture); + Mono>> result = adapter.getState(request, TypeRef.get(MyObject.class)); + settableFuture.set(responseEnvelope); + assertEquals(expectedState, result.block().getObject()); + } + @Test public void getStateObjectValueWithOptionsNoConcurrencyTest() throws IOException { String etag = "ETag1"; @@ -779,6 +811,27 @@ public class DaprClientGrpcTest { assertTrue(callback.wasCalled); } + @Test + public void deleteStateWithMetadata() { + String etag = "ETag1"; + String key = "key1"; + StateOptions options = buildStateOptions(StateOptions.Consistency.STRONG, StateOptions.Concurrency.FIRST_WRITE); + Map metadata = new HashMap(); + metadata.put("key_1", "val_1"); + SettableFuture settableFuture = SettableFuture.create(); + MockCallback callback = new MockCallback<>(Empty.newBuilder().build()); + addCallback(settableFuture, callback, directExecutor()); + when(client.deleteState(any(io.dapr.v1.DaprProtos.DeleteStateRequest.class))) + .thenReturn(settableFuture); + DeleteStateRequestBuilder builder = new DeleteStateRequestBuilder(STATE_STORE_NAME, key); + builder.withEtag(etag).withStateOptions(options).withMetadata(metadata); + DeleteStateRequest request = builder.build(); + Mono> result = adapter.deleteState(request); + settableFuture.set(Empty.newBuilder().build()); + result.block(); + assertTrue(callback.wasCalled); + } + @Test public void deleteStateTestNoHotMono() { String etag = "ETag1"; diff --git a/sdk/src/test/java/io/dapr/client/DaprClientHttpTest.java b/sdk/src/test/java/io/dapr/client/DaprClientHttpTest.java index 47b47281a..019fb7ef9 100644 --- a/sdk/src/test/java/io/dapr/client/DaprClientHttpTest.java +++ b/sdk/src/test/java/io/dapr/client/DaprClientHttpTest.java @@ -4,10 +4,14 @@ */ package io.dapr.client; +import io.dapr.client.domain.DeleteStateRequestBuilder; +import io.dapr.client.domain.GetStateRequestBuilder; import io.dapr.client.domain.HttpExtension; +import io.dapr.client.domain.Response; import io.dapr.client.domain.State; import io.dapr.client.domain.StateOptions; import io.dapr.config.Properties; +import io.dapr.utils.TypeRef; import okhttp3.OkHttpClient; import okhttp3.mock.Behavior; import okhttp3.mock.MockInterceptor; @@ -406,6 +410,21 @@ public class DaprClientHttpTest { assertEquals(monoEmptyEtag.block().getKey(), "key"); } + @Test + public void getStateWithMetadata() { + Map metadata = new HashMap(); + metadata.put("key_1", "val_1"); + mockInterceptor.addRule() + .get("http://127.0.0.1:3000/v1.0/state/MyStateStore/key?key_1=val_1") + .respond("\"" + EXPECTED_RESULT + "\""); + daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); + daprClientHttp = new DaprClientHttp(daprHttp); + GetStateRequestBuilder builder = new GetStateRequestBuilder(STATE_STORE_NAME, "key"); + builder.withMetadata(metadata).withEtag(""); + Mono>> monoMetadata = daprClientHttp.getState(builder.build(), TypeRef.get(String.class)); + assertEquals(monoMetadata.block().getObject().getKey(), "key"); + } + @Test public void getStatesNullEtag() { State stateNullEtag = new State("value", "key", null, null); @@ -529,6 +548,23 @@ public class DaprClientHttpTest { assertNull(mono.block()); } + @Test + public void deleteStateWithMetadata() { + Map metadata = new HashMap(); + metadata.put("key_1", "val_1"); + StateOptions stateOptions = mock(StateOptions.class); + State stateKeyValue = new State("value", "key", "etag", stateOptions); + mockInterceptor.addRule() + .delete("http://127.0.0.1:3000/v1.0/state/MyStateStore/key?key_1=val_1") + .respond(EXPECTED_RESULT); + daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient); + daprClientHttp = new DaprClientHttp(daprHttp); + DeleteStateRequestBuilder builder = new DeleteStateRequestBuilder(STATE_STORE_NAME, stateKeyValue.getKey()); + builder.withMetadata(metadata).withEtag(stateKeyValue.getEtag()).withStateOptions(stateOptions); + Mono> monoMetadata = daprClientHttp.deleteState(builder.build()); + assertNull(monoMetadata.block().getObject()); + } + @Test public void deleteStateNoHotMono() { StateOptions stateOptions = mock(StateOptions.class);