Add metadata for state save operation (#397)

* add metadata for state save

* add test case for state hashcode() and equals()

* add metadata for state tansactional

Co-authored-by: Artur Souza <artursouza.ms@outlook.com>
This commit is contained in:
Sky/敖小剑 2020-12-02 13:13:25 +08:00 committed by GitHub
parent 8cc33b5598
commit 912ff7a781
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 88 additions and 2 deletions

View File

@ -426,6 +426,9 @@ public class DaprClientGrpc extends AbstractDaprClient {
if (state.getEtag() != null) {
stateBuilder.setEtag(state.getEtag());
}
if (state.getMetadata() != null) {
stateBuilder.putAllMetadata(state.getMetadata());
}
if (bytes != null) {
stateBuilder.setValue(ByteString.copyFrom(bytes));
}

View File

@ -411,7 +411,7 @@ public class DaprClientHttp extends AbstractDaprClient {
byte[] data = this.stateSerializer.serialize(state.getValue());
// Custom serializer, so everything is byte[].
operations.add(new TransactionalStateOperation<>(operation.getOperation(),
new State<>(data, state.getKey(), state.getEtag(), state.getOptions())));
new State<>(data, state.getKey(), state.getEtag(), state.getMetadata(), state.getOptions())));
}
TransactionalStateRequest<Object> req = new TransactionalStateRequest<>(internalOperationObjects, metadata);
byte[] serializedOperationBody = INTERNAL_SERIALIZER.serialize(req);
@ -461,7 +461,8 @@ public class DaprClientHttp extends AbstractDaprClient {
byte[] data = this.stateSerializer.serialize(state.getValue());
// Custom serializer, so everything is byte[].
internalStateObjects.add(new State<>(data, state.getKey(), state.getEtag(), state.getOptions()));
internalStateObjects.add(new State<>(data, state.getKey(), state.getEtag(), state.getMetadata(),
state.getOptions()));
}
byte[] serializedStateBody = INTERNAL_SERIALIZER.serialize(internalStateObjects);
return this.client.invokeApi(

View File

@ -5,6 +5,8 @@
package io.dapr.client.domain;
import java.util.Map;
/**
* This class reprent what a State is.
*
@ -28,6 +30,11 @@ public class State<T> {
*/
private final String etag;
/**
* The metadata which will be passed to state store component.
*/
private final Map<String, String> metadata;
/**
* The error in case the key could not be retrieved.
*/
@ -48,6 +55,7 @@ public class State<T> {
this.key = key;
this.value = null;
this.etag = null;
this.metadata = null;
this.options = null;
this.error = null;
}
@ -65,6 +73,7 @@ public class State<T> {
this.value = null;
this.key = key;
this.etag = etag;
this.metadata = null;
this.options = options;
this.error = null;
}
@ -82,6 +91,26 @@ public class State<T> {
this.value = value;
this.key = key;
this.etag = etag;
this.metadata = null;
this.options = options;
this.error = null;
}
/**
* Create an immutable state.
* This Constructor CAN be used anytime you want the state to be saved.
*
* @param value - The value of the state.
* @param key - The key of the state.
* @param etag - The etag of the state - for some state stores (like redis) only numbers are supported.
* @param metadata - The metadata of the state.
* @param options - REQUIRED when saving a state.
*/
public State(T value, String key, String etag, Map<String, String> metadata, StateOptions options) {
this.value = value;
this.key = key;
this.etag = etag;
this.metadata = metadata;
this.options = options;
this.error = null;
}
@ -98,6 +127,7 @@ public class State<T> {
this.value = value;
this.key = key;
this.etag = etag;
this.metadata = null;
this.options = null;
this.error = null;
}
@ -113,6 +143,7 @@ public class State<T> {
this.value = null;
this.key = key;
this.etag = null;
this.metadata = null;
this.options = null;
this.error = error;
}
@ -144,6 +175,14 @@ public class State<T> {
return etag;
}
/**
* Retrieve the metadata of this state.
* @return the metadata of this state
*/
public Map<String, String> getMetadata() {
return metadata;
}
/**
* Retrieve the error for this state.
*
@ -191,6 +230,10 @@ public class State<T> {
return false;
}
if (getMetadata() != null ? !getMetadata().equals(that.getMetadata()) : that.getMetadata() != null) {
return false;
}
if (getOptions() != null ? !getOptions().equals(that.getOptions()) : that.getOptions() != null) {
return false;
}
@ -203,6 +246,7 @@ public class State<T> {
int result = getValue() != null ? getValue().hashCode() : 0;
result = 31 * result + (getKey() != null ? getKey().hashCode() : 0);
result = 31 * result + (getEtag() != null ? getEtag().hashCode() : 0);
result = 31 * result + (getMetadata() != null ? getMetadata().hashCode() : 0);
result = 31 * result + (getError() != null ? getError().hashCode() : 0);
result = 31 * result + (getOptions() != null ? options.hashCode() : 0);
return result;
@ -214,6 +258,7 @@ public class State<T> {
+ "value=" + value
+ ", key='" + key + "'"
+ ", etag='" + etag + "'"
+ ", metadata={'" + (metadata != null ? metadata.toString() : null) + "'}"
+ ", error='" + error + "'"
+ ", options={'" + (options != null ? options.toString() : null) + "'}"
+ "}";

View File

@ -5,11 +5,22 @@ import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertNotEquals;
import java.util.HashMap;
import java.util.Map;
public class StateTest {
private static final String KEY = "key";
private static final String ETAG = "111";
private static final Map<String, String> METADATA = new HashMap<>();
static {
METADATA.put("key1", "value1");
METADATA.put("key2", "value2");
METADATA.put("key3", "value3");
METADATA.put("key4", "value4");
}
private static final StateOptions OPTIONS = new StateOptions(StateOptions.Consistency.STRONG,
StateOptions.Concurrency.FIRST_WRITE);
@ -26,6 +37,7 @@ public class StateTest {
+ "value=value"
+ ", key='" + KEY + "'"
+ ", etag='" + ETAG + "'"
+ ", metadata={'null'}"
+ ", error='null'"
+ ", options={'null'}"
+ "}";
@ -45,6 +57,7 @@ public class StateTest {
+ "value=null"
+ ", key='" + KEY + "'"
+ ", etag='" + ETAG + "'"
+ ", metadata={'null'}"
+ ", error='null'"
+ ", options={'" + OPTIONS.toString() + "'}"
+ "}";
@ -63,10 +76,34 @@ public class StateTest {
+ "value=value"
+ ", key='" + KEY + "'"
+ ", etag='" + ETAG + "'"
+ ", metadata={'null'}"
+ ", error='null'"
+ ", options={'" + OPTIONS.toString() + "'}"
+ "}";
assertEquals(expected, state.toString());
assertEquals("value", state.getValue());
}
@Test
public void testEqualsAndHashcode() {
State<String> state1 = new State<>("value", KEY, ETAG, new HashMap<>(METADATA), OPTIONS);
State<String> state2 = new State<>("value", KEY, ETAG, new HashMap<>(METADATA), OPTIONS);
assertEquals(state1.toString(), state2.toString());
assertEquals(state1.hashCode(), state2.hashCode());
assertEquals(state1, state2);
Map<String, String> metadata3 = new HashMap<>(METADATA);
metadata3.put("key5", "value5");
State<String> state3 = new State<>("value", KEY, ETAG, metadata3, OPTIONS);
assertNotEquals(state1.toString(), state3.toString());
assertNotEquals(state1.hashCode(), state3.hashCode());
assertNotEquals(state1, state3);
Map<String, String> metadata4 = new HashMap<>(METADATA);
metadata4.remove("key1");
State<String> state4 = new State<>("value", KEY, ETAG, metadata4, OPTIONS);
assertNotEquals(state1.toString(), state4.toString());
assertNotEquals(state1.hashCode(), state4.hashCode());
assertNotEquals(state1, state4);
}
}