updates per mark review

Signed-off-by: Hannah Hunter <hannahhunter@microsoft.com>
This commit is contained in:
Hannah Hunter 2024-07-23 09:20:48 -04:00
parent d48caef391
commit 52289a9499
1 changed files with 205 additions and 68 deletions

View File

@ -110,19 +110,64 @@ spec:
### Shape the outbox pattern message
You can override the outbox pattern message published to the pub/sub broker by setting a different message. This is done via a projected transaction payload, which is ignored, but used as the outbox pattern message published to the user topic.
You can override the outbox pattern message published to the pub/sub broker by setting a different message. This is done via a projected transaction payload, called `outboxProjections`, which is ignored when the state is written and is used as the outbox pattern message published to the user topic.
In order to override, the `key` values must match between the operation on the state store and the message projection. If the keys do not match, the whole transaction fails.
To set the `outboxProjections` to `true`, the `key` values must match between the operation on the state store and the message projection. If the keys do not match, the whole transaction fails.
If you have two or more `outboxProjections` for the same key, the first one defined is used and the others are ignored.
{{< tabs JavaScript ".NET" Java Go HTTP >}}
[Learn more about default and custom CloudEvent messages.]({{< ref pubsub-cloudevents.md >}})
{{< tabs Python JavaScript ".NET" Java Go HTTP >}}
{{% codetab %}}
<!--python-->
In the following Python SDK example of a state transaction, the value of `"2"` is saved to the database, but the value of `"3"` is published to the end-user topic.
```python
DAPR_STORE_NAME = "statestore"
async def main():
client = DaprClient()
# Define the first state operation to save the value "2"
op1 = StateItem(
key="key1",
value=b"2"
)
# Define the second state operation to publish the value "3" with metadata
op2 = StateItem(
key="key1",
value=b"3",
options=StateOptions(
metadata={
"outbox.projection": "true"
}
)
)
# Create the list of state operations
ops = [op1, op2]
# Execute the state transaction
await client.state.transaction(DAPR_STORE_NAME, operations=ops)
print("State transaction executed.")
```
By setting the metadata item `"outbox.projection"` to `"true"` and making sure the `key` values match (`key1`):
- The first operation is written to the state store and no message is written to the message broker.
- The second operation value is published to the configured pub/sub topic.
{{% /codetab %}}
{{% codetab %}}
<!--javascript-->
In the following .NET SDK example of a state transaction, the value of `"2"` is saved to the database, but the value of `"3"` is published to the end-user topic.
In the following JavaScript SDK example of a state transaction, the value of `"2"` is saved to the database, but the value of `"3"` is published to the end-user topic.
```javascript
const { DaprClient, StateOperationType } = require('@dapr/dapr');
@ -166,7 +211,10 @@ main().catch(err => {
});
```
By setting the metadata item `"outbox.projection"` to `"true"`, the first transaction value published to the broker is ignored, while the second value is published to the configured pub/sub topic.
By setting the metadata item `"outbox.projection"` to `"true"` and making sure the `key` values match (`key1`):
- The first operation is written to the state store and no message is written to the message broker.
- The second operation value is published to the configured pub/sub topic.
{{% /codetab %}}
@ -214,7 +262,9 @@ public class Program
}
```
By setting the metadata item `"outbox.projection"` to `"true"`, the first transaction value published to the broker is ignored, while the second value is published to the configured pub/sub topic.
By setting the metadata item `"outbox.projection"` to `"true"` and making sure the `key` values match (`key1`):
- The first operation is written to the state store and no message is written to the message broker.
- The second operation value is published to the configured pub/sub topic.
{{% /codetab %}}
@ -222,7 +272,7 @@ By setting the metadata item `"outbox.projection"` to `"true"`, the first transa
<!--java-->
In the following Go SDK example of a state transaction, the value of `"2"` is saved to the database, but the value of `"3"` is published to the end-user topic.
In the following Java SDK example of a state transaction, the value of `"2"` is saved to the database, but the value of `"3"` is published to the end-user topic.
```java
public class Main {
@ -263,7 +313,10 @@ public class Main {
}
```
By setting the metadata item `"outbox.projection"` to `"true"`, the first transaction value published to the broker is ignored, while the second value is published to the configured pub/sub topic.
By setting the metadata item `"outbox.projection"` to `"true"` and making sure the `key` values match (`key1`):
- The first operation is written to the state store and no message is written to the message broker.
- The second operation value is published to the configured pub/sub topic.
{{% /codetab %}}
@ -299,7 +352,9 @@ meta := map[string]string{}
err := testClient.ExecuteStateTransaction(ctx, store, meta, ops)
```
By setting the metadata item `"outbox.projection"` to `"true"`, the first transaction value published to the broker is ignored, while the second value is published to the configured pub/sub topic.
By setting the metadata item `"outbox.projection"` to `"true"` and making sure the `key` values match (`key1`):
- The first operation is written to the state store and no message is written to the message broker.
- The second operation value is published to the configured pub/sub topic.
{{% /codetab %}}
@ -335,7 +390,9 @@ curl -X POST http://localhost:3500/v1.0/state/starwars/transaction \
}'
```
By setting the metadata item `"outboxProjection"` to `"true"`, the first transaction value published to the broker is ignored, while the second value is published to the configured pub/sub topic.
By setting the metadata item `"outbox.projection"` to `"true"` and making sure the `key` values match (`key1`):
- The first operation is written to the state store and no message is written to the message broker.
- The second operation value is published to the configured pub/sub topic.
{{% /codetab %}}
@ -343,9 +400,50 @@ By setting the metadata item `"outboxProjection"` to `"true"`, the first transa
### Override Dapr-generated CloudEvent fields
You can also override the [Dapr-generated CloudEvent fields]({{< ref "pubsub-cloudevents.md#dapr-generated-cloudevents-example" >}}) on the published outbox event with custom CloudEvent metadata.
You can override the [Dapr-generated CloudEvent fields]({{< ref "pubsub-cloudevents.md#dapr-generated-cloudevents-example" >}}) on the published outbox event with custom CloudEvent metadata.
{{< tabs JavaScript ".NET" Java Go HTTP >}}
{{< tabs Python JavaScript ".NET" Java Go HTTP >}}
{{% codetab %}}
<!--python-->
```python
async def execute_state_transaction():
async with DaprClient() as client:
# Define state operations
ops = []
op1 = {
'operation': 'upsert',
'request': {
'key': 'key1',
'value': b'2', # Convert string to byte array
'metadata': {
'cloudevent.id': 'unique-business-process-id',
'cloudevent.source': 'CustomersApp',
'cloudevent.type': 'CustomerCreated',
'cloudevent.subject': '123',
'my-custom-ce-field': 'abc'
}
}
}
ops.append(op1)
# Execute state transaction
store_name = 'your-state-store-name'
try:
await client.execute_state_transaction(store_name, ops)
print('State transaction executed.')
except Exception as e:
print('Error executing state transaction:', e)
# Run the async function
if __name__ == "__main__":
asyncio.run(execute_state_transaction())
```
{{% /codetab %}}
{{% codetab %}}
@ -398,32 +496,41 @@ public class StateOperationExample
{
var daprClient = new DaprClientBuilder().Build();
// Define state operations
var ops = new List<StateOperation>();
// Define the value "2" as a string and serialize it to a byte array
var value = "2";
var valueBytes = JsonSerializer.SerializeToUtf8Bytes(value);
var op1 = new StateOperation
// Define the first state operation to save the value "2" with metadata
// Override Cloudevent metadata
var metadata = new Dictionary<string, string>
{
OperationType = StateOperationType.Upsert,
Request = new SetStateRequest
{
Key = "key1",
Value = new byte[] { 50 }, // []byte("2") in Go is equivalent to new byte[] { 50 } in C#
Metadata = new Dictionary<string, string>
{
{ "id", "unique-business-process-id" },
{ "source", "CustomersApp" },
{ "type", "CustomerCreated" },
{ "subject", "123" },
{ "my-custom-ce-field", "abc" }
}
}
{ "cloudevent.id", "unique-business-process-id" },
{ "cloudevent.source", "CustomersApp" },
{ "cloudevent.type", "CustomerCreated" },
{ "cloudevent.subject", "123" },
{ "my-custom-ce-field", "abc" }
};
ops.Add(op1);
var op1 = new StateTransactionRequest(
key: "key1",
value: valueBytes,
operationType: StateOperationType.Upsert,
metadata: metadata
);
// Execute state transaction
// Create the list of state operations
var ops = new List<StateTransactionRequest> { op1 };
// Execute the state transaction
var storeName = "your-state-store-name";
var metadata = new Dictionary<string, string>();
await daprClient.ExecuteStateTransactionAsync(storeName, ops);
Console.WriteLine("State transaction executed.");
}
public static async Task Main(string[] args)
{
var example = new StateOperationExample();
await example.ExecuteStateTransactionAsync();
}
}
```
@ -442,27 +549,36 @@ public class StateOperationExample {
public static void executeStateTransaction() {
// Build Dapr client
DaprClient daprClient = new DaprClientBuilder().build();
try (DaprClient daprClient = new DaprClientBuilder().build()) {
// Define state operations
List<StateOperation<?>> ops = new ArrayList<>();
// Define the value "2"
String value = "2";
State<String> op1 = new State<>(
"key1",
"2",
new StateOptions<>(StateOperation.Type.UPSERT, new HashMap<String, String>() {{
put("id", "unique-business-process-id");
put("source", "CustomersApp");
put("type", "CustomerCreated");
put("subject", "123");
put("my-custom-ce-field", "abc");
}})
);
ops.add(op1);
// Override CloudEvent metadata
Map<String, String> metadata = new HashMap<>();
metadata.put("cloudevent.id", "unique-business-process-id");
metadata.put("cloudevent.source", "CustomersApp");
metadata.put("cloudevent.type", "CustomerCreated");
metadata.put("cloudevent.subject", "123");
metadata.put("my-custom-ce-field", "abc");
// Execute state transaction
String storeName = "your-state-store-name";
Map<String, String> metadata = new HashMap<>();
// Define state operations
List<StateOperation<?>> ops = new ArrayList<>();
StateOperation<String> op1 = new StateOperation<>(
StateOperationType.UPSERT,
"key1",
value,
metadata
);
ops.add(op1);
// Execute state transaction
String storeName = "your-state-store-name";
daprClient.executeStateTransaction(storeName, ops).block();
System.out.println("State transaction executed.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
```
@ -473,26 +589,47 @@ public class StateOperationExample {
<!--go-->
```go
ops := make([]*dapr.StateOperation, 0)
func main() {
// Create a Dapr client
client, err := dapr.NewClient()
if err != nil {
log.Fatalf("failed to create Dapr client: %v", err)
}
defer client.Close()
op1 := &dapr.StateOperation{
Type: dapr.StateOperationTypeUpsert,
Item: &dapr.SetStateItem{
Key: "key1",
Value: []byte("2"),
// Override the data payload saved to the database
Metadata: map[string]string{
"id": "unique-business-process-id",
"source": "CustomersApp",
"type": "CustomerCreated",
"subject": "123",
"my-custom-ce-field": "abc",
},
},
ctx := context.Background()
store := "your-state-store-name"
// Define state operations
ops := make([]*dapr.StateOperation, 0)
op1 := &dapr.StateOperation{
Type: dapr.StateOperationTypeUpsert,
Item: &dapr.SetStateItem{
Key: "key1",
Value: []byte("2"),
// Override Cloudevent metadata
Metadata: map[string]string{
"cloudevent.id": "unique-business-process-id",
"cloudevent.source": "CustomersApp",
"cloudevent.type": "CustomerCreated",
"cloudevent.subject": "123",
"my-custom-ce-field": "abc",
},
},
}
ops = append(ops, op1)
// Metadata for the transaction (if any)
meta := map[string]string{}
// Execute state transaction
err = client.ExecuteStateTransaction(ctx, store, meta, ops)
if err != nil {
log.Fatalf("failed to execute state transaction: %v", err)
}
log.Println("State transaction executed.")
}
ops = append(ops, op1, op2)
meta := map[string]string{}
err := testClient.ExecuteStateTransaction(ctx, store, meta, ops)
```
{{% /codetab %}}