Merge branch 'v1.14' into issue_3915-3

This commit is contained in:
Hannah Hunter 2024-07-24 11:13:52 -04:00 committed by GitHub
commit 51ebfe4c15
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 537 additions and 79 deletions

View File

@ -7,7 +7,7 @@ description: >
How Dapr compares to and works with service meshes
---
Dapr uses a sidecar architecture, running as a separate process alongside the application and includes features such as service invocation, network security, and distributed tracing. This often raises the question: how does Dapr compare to service mesh solutions such as [Linkerd](https://linkerd.io/), [Istio](https://istio.io/) and [Open Service Mesh](https://openservicemesh.io/) among others?
Dapr uses a sidecar architecture, running as a separate process alongside the application and includes features such as service invocation, network security, and [distributed tracing](https://middleware.io/blog/what-is-distributed-tracing/). This often raises the question: how does Dapr compare to service mesh solutions such as [Linkerd](https://linkerd.io/), [Istio](https://istio.io/) and [Open Service Mesh](https://openservicemesh.io/) among others?
## How Dapr and service meshes compare
While Dapr and service meshes do offer some overlapping capabilities, **Dapr is not a service mesh**, where a service mesh is defined as a *networking* service mesh. Unlike a service mesh which is focused on networking concerns, Dapr is focused on providing building blocks that make it easier for developers to build applications as microservices. Dapr is developer-centric, versus service meshes which are infrastructure-centric.

View File

@ -69,7 +69,7 @@ spec:
allowedSecrets: ["secret1", "secret2"]
```
The default access to the `vault` secret store is `deny`, while some secrets are accessible by the application, based on the `allowedSecrets` list. [Learn how to apply configuration to the sidecar]]({{< ref configuration-concept.md >}}).
The default access to the `vault` secret store is `deny`, while some secrets are accessible by the application, based on the `allowedSecrets` list. [Learn how to apply configuration to the sidecar]({{< ref configuration-concept.md >}}).
## Scenario 3: Deny access to certain sensitive secrets in a secret store
@ -88,7 +88,7 @@ spec:
deniedSecrets: ["secret1", "secret2"]
```
This example configuration explicitly denies access to `secret1` and `secret2` from the secret store named `vault` while allowing access to all other secrets. [Learn how to apply configuration to the sidecar]]({{< ref configuration-concept.md >}}).
This example configuration explicitly denies access to `secret1` and `secret2` from the secret store named `vault` while allowing access to all other secrets. [Learn how to apply configuration to the sidecar]({{< ref configuration-concept.md >}}).
## Permission priority

View File

@ -110,9 +110,215 @@ 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.
{{< tabs "Go SDK" HTTP >}}
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.
[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 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');
const DAPR_STORE_NAME = "statestore";
async function main() {
const client = new DaprClient();
// Define the first state operation to save the value "2"
const op1 = {
operation: StateOperationType.UPSERT,
request: {
key: "key1",
value: "2"
}
};
// Define the second state operation to publish the value "3" with metadata
const op2 = {
operation: StateOperationType.UPSERT,
request: {
key: "key1",
value: "3",
metadata: {
"outbox.projection": "true"
}
}
};
// Create the list of state operations
const ops = [op1, op2];
// Execute the state transaction
await client.state.transaction(DAPR_STORE_NAME, ops);
console.log("State transaction executed.");
}
main().catch(err => {
console.error(err);
});
```
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 %}}
<!--dotnet-->
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.
```csharp
public class Program
{
private const string DAPR_STORE_NAME = "statestore";
public static async Task Main(string[] args)
{
var client = new DaprClientBuilder().Build();
// Define the first state operation to save the value "2"
var op1 = new StateTransactionRequest(
key: "key1",
value: Encoding.UTF8.GetBytes("2"),
operationType: StateOperationType.Upsert
);
// Define the second state operation to publish the value "3" with metadata
var metadata = new Dictionary<string, string>
{
{ "outbox.projection", "true" }
};
var op2 = new StateTransactionRequest(
key: "key1",
value: Encoding.UTF8.GetBytes("3"),
operationType: StateOperationType.Upsert,
metadata: metadata
);
// Create the list of state operations
var ops = new List<StateTransactionRequest> { op1, op2 };
// Execute the state transaction
await client.ExecuteStateTransactionAsync(DAPR_STORE_NAME, ops);
Console.WriteLine("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 %}}
<!--java-->
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 {
private static final String DAPR_STORE_NAME = "statestore";
public static void main(String[] args) {
try (DaprClient client = new DaprClientBuilder().build()) {
// Define the first state operation to save the value "2"
StateOperation<String> op1 = new StateOperation<>(
StateOperationType.UPSERT,
"key1",
"2"
);
// Define the second state operation to publish the value "3" with metadata
Map<String, String> metadata = new HashMap<>();
metadata.put("outbox.projection", "true");
StateOperation<String> op2 = new StateOperation<>(
StateOperationType.UPSERT,
"key1",
"3",
metadata
);
// Create the list of state operations
List<StateOperation<?>> ops = new ArrayList<>();
ops.add(op1);
ops.add(op2);
// Execute the state transaction
client.executeStateTransaction(DAPR_STORE_NAME, ops).block();
System.out.println("State transaction executed.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
```
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 %}}
@ -146,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 %}}
@ -182,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 %}}
@ -190,35 +400,236 @@ 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 "Go SDK" 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 %}}
<!--javascript-->
```javascript
const { DaprClient } = require('dapr-client');
async function executeStateTransaction() {
// Initialize Dapr client
const daprClient = new DaprClient();
// Define state operations
const ops = [];
const op1 = {
operationType: 'upsert',
request: {
key: 'key1',
value: Buffer.from('2'),
metadata: {
'id': 'unique-business-process-id',
'source': 'CustomersApp',
'type': 'CustomerCreated',
'subject': '123',
'my-custom-ce-field': 'abc'
}
}
};
ops.push(op1);
// Execute state transaction
const storeName = 'your-state-store-name';
const metadata = {};
}
executeStateTransaction();
```
{{% /codetab %}}
{{% codetab %}}
<!--csharp-->
```csharp
public class StateOperationExample
{
public async Task ExecuteStateTransactionAsync()
{
var daprClient = new DaprClientBuilder().Build();
// Define the value "2" as a string and serialize it to a byte array
var value = "2";
var valueBytes = JsonSerializer.SerializeToUtf8Bytes(value);
// Define the first state operation to save the value "2" with metadata
// Override Cloudevent metadata
var metadata = new Dictionary<string, string>
{
{ "cloudevent.id", "unique-business-process-id" },
{ "cloudevent.source", "CustomersApp" },
{ "cloudevent.type", "CustomerCreated" },
{ "cloudevent.subject", "123" },
{ "my-custom-ce-field", "abc" }
};
var op1 = new StateTransactionRequest(
key: "key1",
value: valueBytes,
operationType: StateOperationType.Upsert,
metadata: metadata
);
// Create the list of state operations
var ops = new List<StateTransactionRequest> { op1 };
// Execute the state transaction
var storeName = "your-state-store-name";
await daprClient.ExecuteStateTransactionAsync(storeName, ops);
Console.WriteLine("State transaction executed.");
}
public static async Task Main(string[] args)
{
var example = new StateOperationExample();
await example.ExecuteStateTransactionAsync();
}
}
```
{{% /codetab %}}
{{% codetab %}}
<!--java-->
```java
public class StateOperationExample {
public static void main(String[] args) {
executeStateTransaction();
}
public static void executeStateTransaction() {
// Build Dapr client
try (DaprClient daprClient = new DaprClientBuilder().build()) {
// Define the value "2"
String value = "2";
// 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");
// 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();
}
}
}
```
{{% /codetab %}}
{{% codetab %}}
<!--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 %}}

View File

@ -61,27 +61,28 @@ Run the `order-processor` service alongside a Dapr sidecar. The Dapr sidecar the
metadata:
name: myresiliency
scopes:
- checkout
- order-processor
spec:
policies:
retries:
retryForever:
policy: constant
maxInterval: 5s
maxRetries: -1
duration: 5s
maxRetries: -1
circuitBreakers:
simpleCB:
maxRequests: 1
timeout: 5s
timeout: 5s
trip: consecutiveFailures >= 5
targets:
apps:
order-processor:
retry: retryForever
circuitBreaker: simpleCB
components:
statestore:
outbound:
retry: retryForever
circuitBreaker: simpleCB
```

View File

@ -7,10 +7,10 @@ description: Get started with the Dapr Workflow building block
---
{{% alert title="Note" color="primary" %}}
Dapr Workflow is currently in beta. [See known limitations for {{% dapr-latest-version cli="true" %}}]({{< ref "workflow-overview.md#limitations" >}}).
Dapr Workflow is currently in beta. [See known limitations for {{% dapr-latest-version cli="true" %}}]({{< ref "workflow-overview.md#limitations" >}}).
{{% /alert %}}
Let's take a look at the Dapr [Workflow building block]({{< ref workflow-overview.md >}}). In this Quickstart, you'll create a simple console application to demonstrate Dapr's workflow programming model and the workflow management APIs.
Let's take a look at the Dapr [Workflow building block]({{< ref workflow-overview.md >}}). In this Quickstart, you'll create a simple console application to demonstrate Dapr's workflow programming model and the workflow management APIs.
In this guide, you'll:
@ -29,8 +29,8 @@ Select your preferred language-specific Dapr SDK before proceeding with the Quic
The `order-processor` console app starts and manages the `order_processing_workflow`, which simulates purchasing items from a store. The workflow consists of five unique workflow activities, or tasks:
- `notify_activity`: Utilizes a logger to print out messages throughout the workflow. These messages notify you when:
- You have insufficient inventory
- Your payment couldn't be processed, etc.
- You have insufficient inventory
- Your payment couldn't be processed, etc.
- `process_payment_activity`: Processes and authorizes the payment.
- `verify_inventory_activity`: Checks the state store to ensure there is enough inventory present for purchase.
- `update_inventory_activity`: Removes the requested items from the state store and updates the store with the new remaining inventory value.
@ -71,10 +71,11 @@ pip3 install -r requirements.txt
In the terminal, start the order processor app alongside a Dapr sidecar using [Multi-App Run]({{< ref multi-app-dapr-run >}}):
```bash
cd workflows/python/sdk
dapr run -f .
```
This starts the `order-processor` app with unique workflow ID and runs the workflow activities.
This starts the `order-processor` app with unique workflow ID and runs the workflow activities.
Expected output:
@ -105,7 +106,7 @@ Running `dapr init` launches the [openzipkin/zipkin](https://hub.docker.com/r/op
docker run -d -p 9411:9411 openzipkin/zipkin
```
View the workflow trace spans in the Zipkin web UI (typically at `http://localhost:9411/zipkin/`).
View the workflow trace spans in the Zipkin web UI (typically at `http://localhost:9411/zipkin/`).
<img src="/images/workflow-trace-spans-zipkin.png" width=800 style="padding-bottom:15px;">
@ -122,9 +123,10 @@ When you ran `dapr run -f .`:
1. The `NotifyActivity` workflow activity sends a notification saying that order `f4e1926e-3721-478d-be8a-f5bebd1995da` has completed.
1. The workflow terminates as completed.
#### `order-processor/app.py`
#### `order-processor/app.py`
In the application's program file:
- The unique workflow order ID is generated
- The workflow is scheduled
- The workflow status is retrieved
@ -276,7 +278,6 @@ The `order-processor` console app starts and manages the lifecycle of an order p
- `processPaymentActivity`: Processes and authorizes the payment.
- `updateInventoryActivity`: Updates the state store with the new remaining inventory value.
### Step 1: Pre-requisites
For this example, you will need:
@ -318,11 +319,11 @@ In the terminal, start the order processor app alongside a Dapr sidecar using [M
dapr run -f .
```
This starts the `order-processor` app with unique workflow ID and runs the workflow activities.
This starts the `order-processor` app with unique workflow ID and runs the workflow activities.
Expected output:
```
```log
== APP - workflowApp == == APP == Orchestration scheduled with ID: 0c332155-1e02-453a-a333-28cfc7777642
== APP - workflowApp == == APP == Waiting 30 seconds for instance 0c332155-1e02-453a-a333-28cfc7777642 to complete...
== APP - workflowApp == == APP == Received "Orchestrator Request" work item with instance id '0c332155-1e02-453a-a333-28cfc7777642'
@ -393,7 +394,7 @@ Running `dapr init` launches the [openzipkin/zipkin](https://hub.docker.com/r/op
docker run -d -p 9411:9411 openzipkin/zipkin
```
View the workflow trace spans in the Zipkin web UI (typically at `http://localhost:9411/zipkin/`).
View the workflow trace spans in the Zipkin web UI (typically at `http://localhost:9411/zipkin/`).
<img src="/images/workflow-trace-spans-zipkin.png" width=800 style="padding-bottom:15px;">
@ -410,9 +411,10 @@ When you ran `dapr run -f .`:
1. The `notifyActivity` workflow activity sends a notification saying that order `0c332155-1e02-453a-a333-28cfc7777642` has completed.
1. The workflow terminates as completed.
#### `order-processor/workflowApp.ts`
#### `order-processor/workflowApp.ts`
In the application file:
- The unique workflow order ID is generated
- The workflow is scheduled
- The workflow status is retrieved
@ -489,12 +491,12 @@ start().catch((e) => {
{{% codetab %}}
The `order-processor` console app starts and manages the lifecycle of an order processing workflow that stores and retrieves data in a state store. The workflow consists of four workflow activities, or tasks:
- `NotifyActivity`: Utilizes a logger to print out messages throughout the workflow
- `ReserveInventoryActivity`: Checks the state store to ensure that there is enough inventory for the purchase
- `ProcessPaymentActivity`: Processes and authorizes the payment
- `UpdateInventoryActivity`: Removes the requested items from the state store and updates the store with the new remaining inventory value
### Step 1: Pre-requisites
For this example, you will need:
@ -513,10 +515,10 @@ Clone the [sample provided in the Quickstarts repo](https://github.com/dapr/quic
git clone https://github.com/dapr/quickstarts.git
```
In a new terminal window, navigate to the `order-processor` directory:
In a new terminal window, navigate to the `sdk` directory:
```bash
cd workflows/csharp/sdk/order-processor
cd workflows/csharp/sdk
```
### Step 3: Run the order processor app
@ -527,7 +529,7 @@ In the terminal, start the order processor app alongside a Dapr sidecar using [M
dapr run -f .
```
This starts the `order-processor` app with unique workflow ID and runs the workflow activities.
This starts the `order-processor` app with unique workflow ID and runs the workflow activities.
Expected output:
@ -567,7 +569,7 @@ Running `dapr init` launches the [openzipkin/zipkin](https://hub.docker.com/r/op
docker run -d -p 9411:9411 openzipkin/zipkin
```
View the workflow trace spans in the Zipkin web UI (typically at `http://localhost:9411/zipkin/`).
View the workflow trace spans in the Zipkin web UI (typically at `http://localhost:9411/zipkin/`).
<img src="/images/workflow-trace-spans-zipkin.png" width=800 style="padding-bottom:15px;">
@ -584,9 +586,10 @@ When you ran `dapr run -f .`:
1. The `NotifyActivity` workflow activity sends a notification saying that order `6d2abcc9` has completed.
1. The workflow terminates as completed.
#### `order-processor/Program.cs`
#### `order-processor/Program.cs`
In the application's program file:
- The unique workflow order ID is generated
- The workflow is scheduled
- The workflow status is retrieved
@ -717,6 +720,7 @@ class OrderProcessingWorkflow : Workflow<OrderPayload, OrderResult>
#### `order-processor/Activities` directory
The `Activities` directory holds the four workflow activities used by the workflow, defined in the following files:
- `NotifyActivity.cs`
- `ReserveInventoryActivity.cs`
- `ProcessPaymentActivity.cs`
@ -734,22 +738,22 @@ Watch [this video to walk through the Dapr Workflow .NET demo](https://youtu.be/
{{% codetab %}}
The `order-processor` console app starts and manages the lifecycle of an order processing workflow that stores and retrieves data in a state store. The workflow consists of four workflow activities, or tasks:
- `NotifyActivity`: Utilizes a logger to print out messages throughout the workflow
- `RequestApprovalActivity`: Requests approval for processing payment
- `ReserveInventoryActivity`: Checks the state store to ensure that there is enough inventory for the purchase
- `ProcessPaymentActivity`: Processes and authorizes the payment
- `UpdateInventoryActivity`: Removes the requested items from the state store and updates the store with the new remaining inventory value
### Step 1: Pre-requisites
For this example, you will need:
- [Dapr CLI and initialized environment](https://docs.dapr.io/getting-started).
- Java JDK 11 (or greater):
- [Microsoft JDK 11](https://docs.microsoft.com/java/openjdk/download#openjdk-11)
- [Oracle JDK 11](https://www.oracle.com/technetwork/java/javase/downloads/index.html#JDK11)
- [OpenJDK 11](https://jdk.java.net/11/)
- [Microsoft JDK 11](https://docs.microsoft.com/java/openjdk/download#openjdk-11)
- [Oracle JDK 11](https://www.oracle.com/technetwork/java/javase/downloads/index.html#JDK11)
- [OpenJDK 11](https://jdk.java.net/11/)
- [Apache Maven](https://maven.apache.org/install.html) version 3.x.
<!-- IGNORE_LINKS -->
- [Docker Desktop](https://www.docker.com/products/docker-desktop)
@ -780,10 +784,11 @@ mvn clean install
In the terminal, start the order processor app alongside a Dapr sidecar using [Multi-App Run]({{< ref multi-app-dapr-run >}}):
```bash
cd workflows/java/sdk
dapr run -f .
```
This starts the `order-processor` app with unique workflow ID and runs the workflow activities.
This starts the `order-processor` app with unique workflow ID and runs the workflow activities.
Expected output:
@ -826,7 +831,7 @@ Running `dapr init` launches the [openzipkin/zipkin](https://hub.docker.com/r/op
docker run -d -p 9411:9411 openzipkin/zipkin
```
View the workflow trace spans in the Zipkin web UI (typically at `http://localhost:9411/zipkin/`).
View the workflow trace spans in the Zipkin web UI (typically at `http://localhost:9411/zipkin/`).
<img src="/images/workflow-trace-spans-zipkin.png" width=800 style="padding-bottom:15px;">
@ -1073,7 +1078,6 @@ The `Activities` directory holds the four workflow activities used by the workfl
<!-- Go -->
{{% codetab %}}
The `order-processor` console app starts and manages the `OrderProcessingWorkflow` workflow, which simulates purchasing items from a store. The workflow consists of five unique workflow activities, or tasks:
- `NotifyActivity`: Utilizes a logger to print out messages throughout the workflow. These messages notify you when:
@ -1102,10 +1106,10 @@ Clone the [sample provided in the Quickstarts repo](https://github.com/dapr/quic
git clone https://github.com/dapr/quickstarts.git
```
In a new terminal window, navigate to the `order-processor` directory:
In a new terminal window, navigate to the `sdk` directory:
```bash
cd workflows/go/sdk/order-processor
cd workflows/go/sdk
```
### Step 3: Run the order processor app
@ -1116,7 +1120,7 @@ In the terminal, start the order processor app alongside a Dapr sidecar using [M
dapr run -f .
```
This starts the `order-processor` app with unique workflow ID and runs the workflow activities.
This starts the `order-processor` app with unique workflow ID and runs the workflow activities.
Expected output:
@ -1157,7 +1161,7 @@ Running `dapr init` launches the [openzipkin/zipkin](https://hub.docker.com/r/op
docker run -d -p 9411:9411 openzipkin/zipkin
```
View the workflow trace spans in the Zipkin web UI (typically at `http://localhost:9411/zipkin/`).
View the workflow trace spans in the Zipkin web UI (typically at `http://localhost:9411/zipkin/`).
<img src="/images/workflow-trace-spans-zipkin.png" width=800 style="padding-bottom:15px;">
@ -1174,9 +1178,10 @@ When you ran `dapr run`:
1. The `NotifyActivity` workflow activity sends a notification saying that order `48ee83b7-5d80-48d5-97f9-6b372f5480a5` has completed.
1. The workflow terminates as completed.
#### `order-processor/main.go`
#### `order-processor/main.go`
In the application's program file:
- The unique workflow order ID is generated
- The workflow is scheduled
- The workflow status is retrieved
@ -1317,6 +1322,7 @@ Meanwhile, the `OrderProcessingWorkflow` and its activities are defined as metho
{{< /tabs >}}
## Tell us what you think!
We're continuously working to improve our Quickstart examples and value your feedback. Did you find this Quickstart helpful? Do you have suggestions for improvement?
Join the discussion in our [discord channel](https://discord.com/channels/778680217417809931/953427615916638238).

View File

@ -282,4 +282,4 @@ Using regular expressions to reduce metrics cardinality is considered legacy. We
## References
* [Howto: Run Prometheus locally]({{< ref prometheus.md >}})
* [Howto: Set up Prometheus and Grafana for metrics]({{< ref grafana.md >}})
* [Howto: Set up Prometheus and Grafana for metrics]({{< ref grafana.md >}})

View File

@ -45,6 +45,7 @@ The table below shows the versions of Dapr releases that have been tested togeth
| Release date | Runtime | CLI | SDKs | Dashboard | Status | Release notes |
|--------------------|:--------:|:--------|---------|---------|---------|------------|
| June 28th 2024 | 1.13.5</br> | 1.13.0 | Java 1.11.0 </br>Go 1.10.0 </br>PHP 1.2.0 </br>Python 1.13.0 </br>.NET 1.13.0 </br>JS 3.3.0 | 0.14.0 | Supported (current) | [v1.13.5 release notes](https://github.com/dapr/dapr/releases/tag/v1.13.5) |
| May 29th 2024 | 1.13.4</br> | 1.13.0 | Java 1.11.0 </br>Go 1.10.0 </br>PHP 1.2.0 </br>Python 1.13.0 </br>.NET 1.13.0 </br>JS 3.3.0 | 0.14.0 | Supported (current) | [v1.13.4 release notes](https://github.com/dapr/dapr/releases/tag/v1.13.4) |
| May 21st 2024 | 1.13.3</br> | 1.13.0 | Java 1.11.0 </br>Go 1.10.0 </br>PHP 1.2.0 </br>Python 1.13.0 </br>.NET 1.13.0 </br>JS 3.3.0 | 0.14.0 | Supported (current) | [v1.13.3 release notes](https://github.com/dapr/dapr/releases/tag/v1.13.3) |
| April 3rd 2024 | 1.13.2</br> | 1.13.0 | Java 1.11.0 </br>Go 1.10.0 </br>PHP 1.2.0 </br>Python 1.13.0 </br>.NET 1.13.0 </br>JS 3.3.0 | 0.14.0 | Supported (current) | [v1.13.2 release notes](https://github.com/dapr/dapr/releases/tag/v1.13.2) |
@ -137,9 +138,7 @@ General guidance on upgrading can be found for [self hosted mode]({{< ref self-h
| 1.10.0 | N/A | 1.10.8 |
| 1.11.0 | N/A | 1.11.4 |
| 1.12.0 | N/A | 1.12.4 |
| 1.13.0 | N/A | 1.13.2 |
| 1.13.0 | N/A | 1.13.3 |
| 1.13.0 | N/A | 1.13.4 |
| 1.13.0 | N/A | 1.13.5 |
## Upgrade on Hosting platforms

View File

@ -181,6 +181,23 @@ When subscribing to a topic, you can configure `bulkSubscribe` options. Refer to
Follow the instructions [here](https://learn.microsoft.com/azure/service-bus-messaging/service-bus-quickstart-portal) on setting up Azure Service Bus Queues.
{{% alert title="Note" color="primary" %}}
Your queue must have the same name as the topic you are publishing to with Dapr. For example, if you are publishing to the pub/sub `"myPubsub"` on the topic `"orders"`, your queue must be named `"orders"`.
If you are using a shared access policy to connect to the queue, that policy must be able to "manage" the queue. To work with a dead-letter queue, the policy must live on the Service Bus Namespace that contains both the main queue and the dead-letter queue.
{{% /alert %}}
### Retry policy and dead-letter queues
By default, an Azure Service Bus Queue has a dead-letter queue. The messages are retried the amount given for `maxDeliveryCount`. The default `maxDeliveryCount` value defaults to 10, but can be set up to 2000. These retries happen very rapidly and the message is put in the dead-letter queue if no success is returned.
Dapr Pub/sub offers its own dead-letter queue concept that lets you control the retry policy and subscribe to the dead-letter queue through Dapr.
1. Set up a separate queue as that dead-letter queue in the Azure Service Bus namespace, and a resilience policy that defines how to retry.
1. Subscribe to the topic to get the failed messages and deal with them.
For example, setting up a dead-letter queue `orders-dlq` in the subscription and a resiliency policy lets you subscribe to the topic `orders-dlq` to handle failed messages.
For more details on setting up dead-letter queues, see the [dead-letter article]({{< ref pubsub-deadletter >}}).
## Related links
- [Basic schema for a Dapr component]({{< ref component-schema >}})

View File

@ -451,6 +451,30 @@ You can set a time-to-live (TTL) value at either the message or component level.
If you set both component-level and message-level TTL, the default component-level TTL is ignored in favor of the message-level TTL.
{{% /alert %}}
## Single Active Consumer
The RabbitMQ [Single Active Consumer](https://www.rabbitmq.com/docs/consumers#single-active-consumer) setup ensures that only one consumer at a time processes messages from a queue and switches to another registered consumer if the active one is canceled or fails. This approach might be required when it is crucial for messages to be consumed in the exact order they arrive in the queue and if distributed processing with multiple instances is not supported.
When this option is enabled on a queue by Dapr, an instance of the Dapr runtime will be the single active consumer. To allow another application instance to take over in case of failure, Dapr runtime must [probe the application's health]({{< ref "app-health.md" >}}) and unsubscribe from the pub/sub component.
{{% alert title="Note" color="primary" %}}
This pattern will prevent the application to scale as only one instance can process the load. While it might be interesting for Dapr integration with legacy or sensible applications, you should consider a design allowing distributed processing if you need scalability.
{{% /alert %}}
```yml
apiVersion: dapr.io/v2alpha1
kind: Subscription
metadata:
name: pubsub
spec:
topic: orders
routes:
default: /orders
pubsubname: order-pub-sub
metadata:
singleActiveConsumer: "true"
```
## Related links
- [Basic schema for a Dapr component]({{< ref component-schema >}}) in the Related links section

View File

@ -1 +1 @@
{{- if .Get "short" }}1.13{{ else if .Get "long" }}1.13.4{{ else if .Get "cli" }}1.13.0{{ else }}1.13.4{{ end -}}
{{- if .Get "short" }}1.13{{ else if .Get "long" }}1.13.5{{ else if .Get "cli" }}1.13.0{{ else }}1.13.5{{ end -}}

@ -1 +1 @@
Subproject commit c07eb698ac5d1b152a60d76c64af4841ffa07397
Subproject commit 56367963f46257fbcb109f671ac78dc445435012

@ -1 +1 @@
Subproject commit 5ef7aa2234d4d4c07769ad31cde223ef11c4e33e
Subproject commit 7c03c7ce58d100a559ac1881bc0c80d6dedc5ab9

@ -1 +1 @@
Subproject commit 2f5947392a33bc7911e6669601ddb9e8b59b58fe
Subproject commit a98327e7d9a81611b0d7e91e59ea23ad48271948

@ -1 +1 @@
Subproject commit 4189a3d2ad6897406abd766f4ccbf2300c8f8852
Subproject commit 7350742b6869cc166633d1f4d17d76fbdbb12921

@ -1 +1 @@
Subproject commit 0b7aafdab1d4fade424b1b6c9569329ad10bb516
Subproject commit 64a4f2f6658e9023e8ea080eefdb019645cae802

@ -1 +1 @@
Subproject commit ed283c2e259c21cc77a24b3dbc03733103455f1b
Subproject commit 4abf5aa6504f7c0b0018d20f8dc038a486a67e3a