mirror of https://github.com/dapr/java-sdk.git
				
				
				
			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:
		
							parent
							
								
									8cc33b5598
								
							
						
					
					
						commit
						912ff7a781
					
				|  | @ -426,6 +426,9 @@ public class DaprClientGrpc extends AbstractDaprClient { | ||||||
|     if (state.getEtag() != null) { |     if (state.getEtag() != null) { | ||||||
|       stateBuilder.setEtag(state.getEtag()); |       stateBuilder.setEtag(state.getEtag()); | ||||||
|     } |     } | ||||||
|  |     if (state.getMetadata() != null) { | ||||||
|  |       stateBuilder.putAllMetadata(state.getMetadata()); | ||||||
|  |     } | ||||||
|     if (bytes != null) { |     if (bytes != null) { | ||||||
|       stateBuilder.setValue(ByteString.copyFrom(bytes)); |       stateBuilder.setValue(ByteString.copyFrom(bytes)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -411,7 +411,7 @@ public class DaprClientHttp extends AbstractDaprClient { | ||||||
|         byte[] data = this.stateSerializer.serialize(state.getValue()); |         byte[] data = this.stateSerializer.serialize(state.getValue()); | ||||||
|         // Custom serializer, so everything is byte[]. |         // Custom serializer, so everything is byte[]. | ||||||
|         operations.add(new TransactionalStateOperation<>(operation.getOperation(), |         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); |       TransactionalStateRequest<Object> req = new TransactionalStateRequest<>(internalOperationObjects, metadata); | ||||||
|       byte[] serializedOperationBody = INTERNAL_SERIALIZER.serialize(req); |       byte[] serializedOperationBody = INTERNAL_SERIALIZER.serialize(req); | ||||||
|  | @ -461,7 +461,8 @@ public class DaprClientHttp extends AbstractDaprClient { | ||||||
| 
 | 
 | ||||||
|         byte[] data = this.stateSerializer.serialize(state.getValue()); |         byte[] data = this.stateSerializer.serialize(state.getValue()); | ||||||
|         // Custom serializer, so everything is byte[]. |         // 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); |       byte[] serializedStateBody = INTERNAL_SERIALIZER.serialize(internalStateObjects); | ||||||
|       return this.client.invokeApi( |       return this.client.invokeApi( | ||||||
|  |  | ||||||
|  | @ -5,6 +5,8 @@ | ||||||
| 
 | 
 | ||||||
| package io.dapr.client.domain; | package io.dapr.client.domain; | ||||||
| 
 | 
 | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * This class reprent what a State is. |  * This class reprent what a State is. | ||||||
|  * |  * | ||||||
|  | @ -28,6 +30,11 @@ public class State<T> { | ||||||
|    */ |    */ | ||||||
|   private final String etag; |   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. |    * The error in case the key could not be retrieved. | ||||||
|    */ |    */ | ||||||
|  | @ -48,6 +55,7 @@ public class State<T> { | ||||||
|     this.key = key; |     this.key = key; | ||||||
|     this.value = null; |     this.value = null; | ||||||
|     this.etag = null; |     this.etag = null; | ||||||
|  |     this.metadata = null; | ||||||
|     this.options = null; |     this.options = null; | ||||||
|     this.error = null; |     this.error = null; | ||||||
|   } |   } | ||||||
|  | @ -65,6 +73,7 @@ public class State<T> { | ||||||
|     this.value = null; |     this.value = null; | ||||||
|     this.key = key; |     this.key = key; | ||||||
|     this.etag = etag; |     this.etag = etag; | ||||||
|  |     this.metadata = null; | ||||||
|     this.options = options; |     this.options = options; | ||||||
|     this.error = null; |     this.error = null; | ||||||
|   } |   } | ||||||
|  | @ -82,6 +91,26 @@ public class State<T> { | ||||||
|     this.value = value; |     this.value = value; | ||||||
|     this.key = key; |     this.key = key; | ||||||
|     this.etag = etag; |     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.options = options; | ||||||
|     this.error = null; |     this.error = null; | ||||||
|   } |   } | ||||||
|  | @ -98,6 +127,7 @@ public class State<T> { | ||||||
|     this.value = value; |     this.value = value; | ||||||
|     this.key = key; |     this.key = key; | ||||||
|     this.etag = etag; |     this.etag = etag; | ||||||
|  |     this.metadata = null; | ||||||
|     this.options = null; |     this.options = null; | ||||||
|     this.error = null; |     this.error = null; | ||||||
|   } |   } | ||||||
|  | @ -113,6 +143,7 @@ public class State<T> { | ||||||
|     this.value = null; |     this.value = null; | ||||||
|     this.key = key; |     this.key = key; | ||||||
|     this.etag = null; |     this.etag = null; | ||||||
|  |     this.metadata = null; | ||||||
|     this.options = null; |     this.options = null; | ||||||
|     this.error = error; |     this.error = error; | ||||||
|   } |   } | ||||||
|  | @ -144,6 +175,14 @@ public class State<T> { | ||||||
|     return etag; |     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. |    * Retrieve the error for this state. | ||||||
|    * |    * | ||||||
|  | @ -191,6 +230,10 @@ public class State<T> { | ||||||
|       return false; |       return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if (getMetadata() != null ? !getMetadata().equals(that.getMetadata()) : that.getMetadata() != null) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     if (getOptions() != null ? !getOptions().equals(that.getOptions()) : that.getOptions() != null) { |     if (getOptions() != null ? !getOptions().equals(that.getOptions()) : that.getOptions() != null) { | ||||||
|       return false; |       return false; | ||||||
|     } |     } | ||||||
|  | @ -203,6 +246,7 @@ public class State<T> { | ||||||
|     int result = getValue() != null ? getValue().hashCode() : 0; |     int result = getValue() != null ? getValue().hashCode() : 0; | ||||||
|     result = 31 * result + (getKey() != null ? getKey().hashCode() : 0); |     result = 31 * result + (getKey() != null ? getKey().hashCode() : 0); | ||||||
|     result = 31 * result + (getEtag() != null ? getEtag().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 + (getError() != null ? getError().hashCode() : 0); | ||||||
|     result = 31 * result + (getOptions() != null ? options.hashCode() : 0); |     result = 31 * result + (getOptions() != null ? options.hashCode() : 0); | ||||||
|     return result; |     return result; | ||||||
|  | @ -214,6 +258,7 @@ public class State<T> { | ||||||
|         + "value=" + value |         + "value=" + value | ||||||
|         + ", key='" + key + "'" |         + ", key='" + key + "'" | ||||||
|         + ", etag='" + etag + "'" |         + ", etag='" + etag + "'" | ||||||
|  |         + ", metadata={'" + (metadata != null ? metadata.toString() : null) + "'}" | ||||||
|         + ", error='" + error + "'" |         + ", error='" + error + "'" | ||||||
|         + ", options={'" + (options != null ? options.toString() : null) + "'}" |         + ", options={'" + (options != null ? options.toString() : null) + "'}" | ||||||
|         + "}"; |         + "}"; | ||||||
|  |  | ||||||
|  | @ -5,11 +5,22 @@ import org.junit.Test; | ||||||
| import static org.junit.Assert.assertEquals; | import static org.junit.Assert.assertEquals; | ||||||
| import static org.junit.Assert.assertNotNull; | import static org.junit.Assert.assertNotNull; | ||||||
| import static org.junit.Assert.assertNull; | import static org.junit.Assert.assertNull; | ||||||
|  | import static org.junit.Assert.assertNotEquals; | ||||||
|  | 
 | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.Map; | ||||||
| 
 | 
 | ||||||
| public class StateTest { | public class StateTest { | ||||||
| 
 | 
 | ||||||
|   private static final String KEY = "key"; |   private static final String KEY = "key"; | ||||||
|   private static final String ETAG = "111"; |   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, |   private static final StateOptions OPTIONS = new StateOptions(StateOptions.Consistency.STRONG, | ||||||
|       StateOptions.Concurrency.FIRST_WRITE); |       StateOptions.Concurrency.FIRST_WRITE); | ||||||
| 
 | 
 | ||||||
|  | @ -26,6 +37,7 @@ public class StateTest { | ||||||
|         + "value=value" |         + "value=value" | ||||||
|         + ", key='" + KEY + "'" |         + ", key='" + KEY + "'" | ||||||
|         + ", etag='" + ETAG + "'" |         + ", etag='" + ETAG + "'" | ||||||
|  |         + ", metadata={'null'}" | ||||||
|         + ", error='null'" |         + ", error='null'" | ||||||
|         + ", options={'null'}" |         + ", options={'null'}" | ||||||
|         + "}"; |         + "}"; | ||||||
|  | @ -45,6 +57,7 @@ public class StateTest { | ||||||
|         + "value=null" |         + "value=null" | ||||||
|         + ", key='" + KEY + "'" |         + ", key='" + KEY + "'" | ||||||
|         + ", etag='" + ETAG + "'" |         + ", etag='" + ETAG + "'" | ||||||
|  |         + ", metadata={'null'}" | ||||||
|         + ", error='null'" |         + ", error='null'" | ||||||
|         + ", options={'" + OPTIONS.toString() + "'}" |         + ", options={'" + OPTIONS.toString() + "'}" | ||||||
|         + "}"; |         + "}"; | ||||||
|  | @ -63,10 +76,34 @@ public class StateTest { | ||||||
|         + "value=value" |         + "value=value" | ||||||
|         + ", key='" + KEY + "'" |         + ", key='" + KEY + "'" | ||||||
|         + ", etag='" + ETAG + "'" |         + ", etag='" + ETAG + "'" | ||||||
|  |         + ", metadata={'null'}" | ||||||
|         + ", error='null'" |         + ", error='null'" | ||||||
|         + ", options={'" + OPTIONS.toString() + "'}" |         + ", options={'" + OPTIONS.toString() + "'}" | ||||||
|         + "}"; |         + "}"; | ||||||
|     assertEquals(expected, state.toString()); |     assertEquals(expected, state.toString()); | ||||||
|     assertEquals("value", state.getValue()); |     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); | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue