Merge branch 'issue_3216' of https://github.com/hhunter-ms/docs into issue_3216

This commit is contained in:
Hannah Hunter 2023-06-05 11:15:33 -04:00
commit 7e7292d395
45 changed files with 1276 additions and 355 deletions

View File

@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
name: Build and Deploy Job
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: recursive
fetch-depth: 0
@ -23,22 +23,19 @@ jobs:
run: cd daprdocs && git submodule update --init --recursive && sudo npm install -D --save autoprefixer && sudo npm install -D --save postcss-cli
- name: Build And Deploy
id: builddeploy
uses: Azure/static-web-apps-deploy@v0.0.1-preview
uses: Azure/static-web-apps-deploy@v1
env:
HUGO_ENV: production
HUGO_VERSION: "0.100.2"
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_PROUD_BAY_0E9E0E81E }}
repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
skip_deploy_on_missing_secrets: true
repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
action: "upload"
###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
# For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
app_location: "/daprdocs" # App source code path
api_location: "api" # Api source code path - optional
output_location: "public" # Built app content directory - optional
app_build_command: "hugo"
###### End of Repository/Build Configurations ######
app_location: "/daprdocs"
app_build_command: "git config --global --add safe.directory /github/workspace && hugo"
output_location: "public"
skip_api_build: true
close_pull_request_job:
if: github.event_name == 'pull_request' && github.event.action == 'closed'
@ -47,8 +44,7 @@ jobs:
steps:
- name: Close Pull Request
id: closepullrequest
uses: Azure/static-web-apps-deploy@v0.0.1-preview
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_PROUD_BAY_0E9E0E81E }}
skip_deploy_on_missing_secrets: true
action: "close"

View File

@ -27,7 +27,7 @@ The following are the building blocks provided by Dapr:
| [**Actors**]({{< ref "actors-overview.md" >}}) | `/v1.0/actors` | An actor is an isolated, independent unit of compute and state with single-threaded execution. Dapr provides an actor implementation based on the virtual actor pattern which provides a single-threaded programming model and where actors are garbage collected when not in use.
| [**Observability**]({{< ref "observability-concept.md" >}}) | `N/A` | Dapr system components and runtime emit metrics, logs, and traces to debug, operate and monitor Dapr system services, components and user applications.
| [**Secrets**]({{< ref "secrets-overview.md" >}}) | `/v1.0/secrets` | Dapr provides a secrets building block API and integrates with secret stores such as public cloud stores, local stores and Kubernetes to store the secrets. Services can call the secrets API to retrieve secrets, for example to get a connection string to a database.
| [**Configuration**]({{< ref "configuration-api-overview.md" >}}) | `/v1.0-alpha1/configuration` | The Configuration API enables you to retrieve and subscribe to application configuration items for supported configuration stores. This enables an application to retrieve specific configuration information, for example, at start up or when configuration changes are made in the store.
| [**Configuration**]({{< ref "configuration-api-overview.md" >}}) | `/v1.0/configuration` | The Configuration API enables you to retrieve and subscribe to application configuration items for supported configuration stores. This enables an application to retrieve specific configuration information, for example, at start up or when configuration changes are made in the store.
| [**Distributed lock**]({{< ref "distributed-lock-api-overview.md" >}}) | `/v1.0-alpha1/lock` | The distributed lock API enables you to take a lock on a resource so that multiple instances of an application can access the resource without conflicts and provide consistency guarantees.
| [**Workflows**]({{< ref "workflow-overview.md" >}}) | `/v1.0-alpha1/workflow` | The Workflow API enables you to define long running, persistent processes or data flows that span multiple microservices using Dapr workflows or workflow components. The Workflow API can be combined with other Dapr API building blocks. For example, a workflow can call another service with service invocation or retrieve secrets, providing flexibility and portability.
| [**Cryptography**]({{< ref "cryptography-overview.md" >}}) | `/v1.0-alpha1/crypto` | The Cryptography API enables you to perform cryptographic operations, such as encrypting and decrypting messages, without exposing keys to your application.

View File

@ -90,9 +90,6 @@ The Dapr actor runtime provides a simple turn-based access model for accessing a
Transactional state stores can be used to store actor state. To specify which state store to use for actors, specify value of property `actorStateStore` as `true` in the state store component's metadata section. Actors state is stored with a specific scheme in transactional state stores, allowing for consistent querying. Only a single state store component can be used as the state store for all actors. Read the [state API reference]({{< ref state_api.md >}}) and the [actors API reference]({{< ref actors_api.md >}}) to learn more about state stores for actors.
#### Time to Live (TTL) on state
You should always set the TTL metadata field (`ttlInSeconds`), or the equivalent API call in your chosen SDK when saving actor state to ensure that state eventually removed. Read [actors overview]({{< ref actors-overview.md >}}) for more information.
### Actor timers and reminders
Actors can schedule periodic work on themselves by registering either timers or reminders.

View File

@ -40,6 +40,11 @@ Want to put the Dapr configuration API to the test? Walk through the following q
Want to skip the quickstarts? Not a problem. You can try out the configuration building block directly in your application to read and manage configuration data. After [Dapr is installed]({{< ref "getting-started/_index.md" >}}), you can begin using the configuration API starting with [the configuration how-to guide]({{< ref howto-manage-configuration.md >}}).
## Watch the demo
Watch [this demo of using the Dapr Configuration building block](https://youtu.be/tNq-n1XQuLA?t=496)
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/tNq-n1XQuLA?start=496" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
## Next steps
Follow these guides on:

View File

@ -26,12 +26,12 @@ Create a configuration item in a supported configuration store. This can be a si
docker run --name my-redis -p 6379:6379 -d redis:6
```
### Save an item
### Save an item
Using the [Redis CLI](https://redis.com/blog/get-redis-cli-without-installing-redis-server/), connect to the Redis instance:
```
redis-cli -p 6379
redis-cli -p 6379
```
Save a configuration item:
@ -45,10 +45,10 @@ MSET orderId1 "101||1" orderId2 "102||1"
Save the following component file to the [default components folder]({{< ref "install-dapr-selfhost.md#step-5-verify-components-directory-has-been-initialized" >}}) on your machine. You can use this as the Dapr component YAML:
- For Kubernetes using `kubectl`.
- When running with the Dapr CLI.
- When running with the Dapr CLI.
{{% alert title="Note" color="primary" %}}
Since the Redis configuration component has identical metadata to the Redis `statestore.yaml` component, you can simply copy/change the Redis state store component type if you already have a Redis `statestore.yaml`.
Since the Redis configuration component has identical metadata to the Redis `statestore.yaml` component, you can simply copy/change the Redis state store component type if you already have a Redis `statestore.yaml`.
{{% /alert %}}
@ -67,9 +67,11 @@ spec:
```
## Retrieve Configuration Items
### Get configuration items using Dapr SDKs
### Get configuration items
{{< tabs ".NET" Java Python>}}
The following example shows how to get a saved configuration item using the Dapr Configuration API.
{{< tabs ".NET" Java Python Go Javascript "HTTP API (BASH)" "HTTP API (Powershell)">}}
{{% codetab %}}
@ -87,7 +89,6 @@ namespace ConfigurationApi
{
private static readonly string CONFIG_STORE_NAME = "configstore";
[Obsolete]
public static async Task Main(string[] args)
{
using var client = new DaprClientBuilder().Build();
@ -105,7 +106,7 @@ namespace ConfigurationApi
```java
//dependencies
import io.dapr.client.DaprClientBuilder;
import io.dapr.client.DaprPreviewClient;
import io.dapr.client.DaprClient;
import io.dapr.client.domain.ConfigurationItem;
import io.dapr.client.domain.GetConfigurationRequest;
import io.dapr.client.domain.SubscribeConfigurationRequest;
@ -116,7 +117,7 @@ import reactor.core.publisher.Mono;
private static final String CONFIG_STORE_NAME = "configstore";
public static void main(String[] args) throws Exception {
try (DaprPreviewClient client = (new DaprClientBuilder()).buildPreviewClient()) {
try (DaprClient client = (new DaprClientBuilder()).build()) {
List<String> keys = new ArrayList<>();
keys.add("orderId1");
keys.add("orderId2");
@ -150,79 +151,31 @@ with DaprClient() as d:
{{% /codetab %}}
{{< /tabs >}}
### Get configuration items using gRPC API
Using your [favorite language](https://grpc.io/docs/languages/), create a Dapr gRPC client from the [Dapr proto](https://github.com/dapr/dapr/blob/master/dapr/proto/runtime/v1/dapr.proto). The following examples show Java, C#, Python and Javascript clients.
{{< tabs Java Dotnet Python Javascript >}}
{{% codetab %}}
```java
```go
package main
Dapr.ServiceBlockingStub stub = Dapr.newBlockingStub(channel);
stub.GetConfigurationAlpha1(new GetConfigurationRequest{ StoreName = "redisconfigstore", Keys = new String[]{"myconfig"} });
```
import (
"context"
"fmt"
{{% /codetab %}}
dapr "github.com/dapr/go-sdk/client"
)
{{% codetab %}}
```csharp
var call = client.GetConfigurationAlpha1(new GetConfigurationRequest { StoreName = "redisconfigstore", Keys = new String[]{"myconfig"} });
```
{{% /codetab %}}
{{% codetab %}}
```python
response = stub.GetConfigurationAlpha1(request={ StoreName: 'redisconfigstore', Keys = ['myconfig'] })
```
{{% /codetab %}}
{{% codetab %}}
```javascript
client.GetConfigurationAlpha1({ StoreName: 'redisconfigstore', Keys = ['myconfig'] })
```
{{% /codetab %}}
{{< /tabs >}}
### Watch configuration items using Dapr SDKs
{{< tabs "Dotnet Extension" "Dotnet Client">}}
{{% codetab %}}
```csharp
[Obsolete("Configuration API is an Alpha API. Obsolete will be removed when the API is no longer Alpha")]
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
var client = new DaprClientBuilder().Build();
return Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(config =>
{
// Get the initial value from the configuration component.
config.AddDaprConfigurationStore("redisconfig", new List<string>() { "withdrawVersion" }, client, TimeSpan.FromSeconds(20));
// Watch the keys in the configuration component and update it in local configurations.
config.AddStreamingDaprConfigurationStore("redisconfig", new List<string>() { "withdrawVersion", "source" }, client, TimeSpan.FromSeconds(20));
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
func main() {
ctx := context.Background()
client, err := dapr.NewClient()
if err != nil {
panic(err)
}
items, err := client.GetConfigurationItems(ctx, "configstore", ["orderId1","orderId2"])
if err != nil {
panic(err)
}
for key, item := range items {
fmt.Printf("get config: key = %s value = %s version = %s",key,(*item).Value, (*item).Version)
}
}
```
@ -230,106 +183,504 @@ public static IHostBuilder CreateHostBuilder(string[] args)
{{% codetab %}}
```js
import { CommunicationProtocolEnum, DaprClient } from "@dapr/dapr";
// JS SDK does not support Configuration API over HTTP protocol yet
const protocol = CommunicationProtocolEnum.GRPC;
const host = process.env.DAPR_HOST ?? "localhost";
const port = process.env.DAPR_GRPC_PORT ?? 3500;
const DAPR_CONFIGURATION_STORE = "configstore";
const CONFIGURATION_ITEMS = ["orderId1", "orderId2"];
async function main() {
const client = new DaprClient(host, port, protocol);
// Get config items from the config store
try {
const config = await client.configuration.get(DAPR_CONFIGURATION_STORE, CONFIGURATION_ITEMS);
Object.keys(config.items).forEach((key) => {
console.log("Configuration for " + key + ":", JSON.stringify(config.items[key]));
});
} catch (error) {
console.log("Could not get config item, err:" + error);
process.exit(1);
}
}
main().catch((e) => console.error(e));
```
{{% /codetab %}}
{{% codetab %}}
Launch a dapr sidecar:
```bash
dapr run --app-id orderprocessing --dapr-http-port 3601
```
In a separate terminal, get the configuration item saved earlier:
```bash
curl http://localhost:3601/v1.0/configuration/configstore?key=orderId1
```
{{% /codetab %}}
{{% codetab %}}
Launch a Dapr sidecar:
```bash
dapr run --app-id orderprocessing --dapr-http-port 3601
```
In a separate terminal, get the configuration item saved earlier:
```powershell
Invoke-RestMethod -Uri 'http://localhost:3601/v1.0/configuration/configstore?key=orderId1'
```
{{% /codetab %}}
{{< /tabs >}}
### Subscribe to configuration item updates
Below are code examples that leverage SDKs to subscribe to keys `[orderId1, orderId2]` using `configstore` store component.
{{< tabs ".NET" "ASP.NET Core" Java Python Go Javascript>}}
{{% codetab %}}
```csharp
public IDictionary<string, string> Data { get; set; } = new Dictionary<string, string>();
public string Id { get; set; } = string.Empty;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Dapr.Client;
public async Task WatchConfiguration(DaprClient daprClient, string store, IReadOnlyList<string> keys, Dictionary<string, string> metadata, CancellationToken token = default)
const string DAPR_CONFIGURATION_STORE = "configstore";
var CONFIGURATION_KEYS = new List<string> { "orderId1", "orderId2" };
var client = new DaprClientBuilder().Build();
// Subscribe for configuration changes
SubscribeConfigurationResponse subscribe = await client.SubscribeConfiguration(DAPR_CONFIGURATION_STORE, CONFIGURATION_ITEMS);
// Print configuration changes
await foreach (var items in subscribe.Source)
{
// Initialize the gRPC Stream that will provide configuration updates.
var subscribeConfigurationResponse = await daprClient.SubscribeConfiguration(store, keys, metadata, token);
// First invocation when app subscribes to config changes only returns subscription id
if (items.Keys.Count == 0)
{
Console.WriteLine("App subscribed to config changes with subscription id: " + subscribe.Id);
subscriptionId = subscribe.Id;
continue;
}
var cfg = System.Text.Json.JsonSerializer.Serialize(items);
Console.WriteLine("Configuration update " + cfg);
}
```
// The response contains a data source which is an IAsyncEnumerable, so it can be iterated through via an awaited foreach.
await foreach (var items in subscribeConfigurationResponse.Source.WithCancellation(token))
Navigate to the directory containing the above code, then run the following command to launch both a Dapr sidecar and the subscriber application:
```bash
dapr run --app-id orderprocessing -- dotnet run
```
{{% /codetab %}}
{{% codetab %}}
```csharp
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Dapr.Client;
using Dapr.Extensions.Configuration;
using System.Collections.Generic;
using System.Threading;
namespace ConfigurationApi
{
public class Program
{
// Each iteration from the stream can contain all the keys that were queried for, so it must be individually iterated through.
var data = new Dictionary<string, string>(Data);
foreach (var item in items)
public static void Main(string[] args)
{
// The Id in the response is used to unsubscribe.
Id = subscribeConfigurationResponse.Id;
data[item.Key] = item.Value;
Console.WriteLine("Starting application.");
CreateHostBuilder(args).Build().Run();
Console.WriteLine("Closing application.");
}
/// <summary>
/// Creates WebHost Builder.
/// </summary>
/// <param name="args">Arguments.</param>
/// <returns>Returns IHostbuilder.</returns>
public static IHostBuilder CreateHostBuilder(string[] args)
{
var client = new DaprClientBuilder().Build();
return Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(config =>
{
// Get the initial value and continue to watch it for changes.
config.AddDaprConfigurationStore("configstore", new List<string>() { "orderId1","orderId2" }, client, TimeSpan.FromSeconds(20));
config.AddStreamingDaprConfigurationStore("configstore", new List<string>() { "orderId1","orderId2" }, client, TimeSpan.FromSeconds(20));
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
Data = data;
}
}
```
Navigate to the directory containing the above code, then run the following command to launch both a Dapr sidecar and the subscriber application:
```bash
dapr run --app-id orderprocessing -- dotnet run
```
{{% /codetab %}}
{{< /tabs >}}
### Watch configuration items using gRPC API
{{% codetab %}}
Create a Dapr gRPC client from the [Dapr proto](https://github.com/dapr/dapr/blob/master/dapr/proto/runtime/v1/dapr.proto) using your [preferred language](https://grpc.io/docs/languages/). Use the `SubscribeConfigurationAlpha1` proto method on your client stub to start subscribing to events. The method accepts the following request object:
```java
import io.dapr.client.DaprClientBuilder;
import io.dapr.client.DaprClient;
import io.dapr.client.domain.ConfigurationItem;
import io.dapr.client.domain.GetConfigurationRequest;
import io.dapr.client.domain.SubscribeConfigurationRequest;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
```proto
message SubscribeConfigurationRequest {
// The name of configuration store.
string store_name = 1;
//code
private static final String CONFIG_STORE_NAME = "configstore";
private static String subscriptionId = null;
// Optional. The key of the configuration item to fetch.
// If set, only query for the specified configuration items.
// Empty list means fetch all.
repeated string keys = 2;
public static void main(String[] args) throws Exception {
try (DaprClient client = (new DaprClientBuilder()).build()) {
// Subscribe for config changes
List<String> keys = new ArrayList<>();
keys.add("orderId1");
keys.add("orderId2");
Flux<SubscribeConfigurationResponse> subscription = client.subscribeConfiguration(DAPR_CONFIGURATON_STORE,keys);
// The metadata which will be sent to configuration store components.
map<string,string> metadata = 3;
// Read config changes for 20 seconds
subscription.subscribe((response) -> {
// First ever response contains the subscription id
if (response.getItems() == null || response.getItems().isEmpty()) {
subscriptionId = response.getSubscriptionId();
System.out.println("App subscribed to config changes with subscription id: " + subscriptionId);
} else {
response.getItems().forEach((k, v) -> {
System.out.println("Configuration update for " + k + ": {'value':'" + v.getValue() + "'}");
});
}
});
Thread.sleep(20000);
}
}
```
Using this method, you can subscribe to changes in specific keys for a given configuration store. gRPC streaming varies widely based on language - see the [gRPC examples here](https://grpc.io/docs/languages/) for usage.
Navigate to the directory containing the above code, then run the following command to launch both a Dapr sidecar and the subscriber application:
Below are the examples in sdks:
```bash
dapr run --app-id orderprocessing -- -- mvn spring-boot:run
{{< tabs Python>}}
{{% /codetab %}}
{{% codetab %}}
```python
#dependencies
from dapr.clients import DaprClient
#code
def handler(id: str, resp: ConfigurationResponse):
for key in resp.items:
print(f"Subscribed item received key={key} value={resp.items[key].value} "
f"version={resp.items[key].version} "
f"metadata={resp.items[key].metadata}", flush=True)
def executeConfiguration():
with DaprClient() as d:
storeName = 'configurationstore'
keys = ['orderId1', 'orderId2']
id = d.subscribe_configuration(store_name=storeName, keys=keys,
handler=handler, config_metadata={})
print("Subscription ID is", id, flush=True)
sleep(20)
executeConfiguration()
```
Navigate to the directory containing the above code, then run the following command to launch both a Dapr sidecar and the subscriber application:
```bash
dapr run --app-id orderprocessing -- python3 OrderProcessingService.py
```
{{% /codetab %}}
{{% codetab %}}
```go
package main
import (
"context"
"fmt"
"time"
dapr "github.com/dapr/go-sdk/client"
)
func main() {
ctx := context.Background()
client, err := dapr.NewClient()
if err != nil {
panic(err)
}
subscribeID, err := client.SubscribeConfigurationItems(ctx, "configstore", []string{"orderId1", "orderId2"}, func(id string, items map[string]*dapr.ConfigurationItem) {
for k, v := range items {
fmt.Printf("get updated config key = %s, value = %s version = %s \n", k, v.Value, v.Version)
}
})
if err != nil {
panic(err)
}
time.Sleep(20*time.Second)
}
```
Navigate to the directory containing the above code, then run the following command to launch both a Dapr sidecar and the subscriber application:
```bash
dapr run --app-id orderprocessing -- go run main.go
```
{{% /codetab %}}
{{% codetab %}}
```js
import { CommunicationProtocolEnum, DaprClient } from "@dapr/dapr";
// JS SDK does not support Configuration API over HTTP protocol yet
const protocol = CommunicationProtocolEnum.GRPC;
const host = process.env.DAPR_HOST ?? "localhost";
const port = process.env.DAPR_GRPC_PORT ?? 3500;
const DAPR_CONFIGURATION_STORE = "configstore";
const CONFIGURATION_ITEMS = ["orderId1", "orderId2"];
async function main() {
const client = new DaprClient(host, port, protocol);
// Subscribe to config updates
try {
const stream = await client.configuration.subscribeWithKeys(
DAPR_CONFIGURATION_STORE,
CONFIGURATION_ITEMS,
(config) => {
console.log("Configuration update", JSON.stringify(config.items));
}
);
// Unsubscribe to config updates and exit app after 20 seconds
setTimeout(() => {
stream.stop();
console.log("App unsubscribed to config changes");
process.exit(0);
}, 20000);
} catch (error) {
console.log("Error subscribing to config updates, err:" + error);
process.exit(1);
}
}
main().catch((e) => console.error(e));
```
Navigate to the directory containing the above code, then run the following command to launch both a Dapr sidecar and the subscriber application:
```bash
dapr run --app-id orderprocessing --app-protocol grpc --dapr-grpc-port 3500 -- node index.js
```
{{% /codetab %}}
{{< /tabs >}}
### Unsubscribe from configuration item updates
After you've subscribed to watch configuration items, you will receive updates for all of the subscribed keys. To stop receiving updates, you need to explicitly call the unsubscribe API.
Following are the code examples showing how you can unsubscribe to configuration updates using unsubscribe API.
{{< tabs ".NET" Java Python Go Javascript "HTTP API (BASH)" "HTTP API (Powershell)">}}
{{% codetab %}}
```csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Dapr.Client;
const string DAPR_CONFIGURATION_STORE = "configstore";
var client = new DaprClientBuilder().Build();
// Unsubscribe to config updates and exit the app
async Task unsubscribe(string subscriptionId)
{
try
{
await client.UnsubscribeConfiguration(DAPR_CONFIGURATION_STORE, subscriptionId);
Console.WriteLine("App unsubscribed from config changes");
Environment.Exit(0);
}
catch (Exception ex)
{
Console.WriteLine("Error unsubscribing from config updates: " + ex.Message);
}
}
```
{{% /codetab %}}
{{% codetab %}}
```java
import io.dapr.client.DaprClientBuilder;
import io.dapr.client.DaprClient;
import io.dapr.client.domain.ConfigurationItem;
import io.dapr.client.domain.GetConfigurationRequest;
import io.dapr.client.domain.SubscribeConfigurationRequest;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
//code
private static final String CONFIG_STORE_NAME = "configstore";
private static String subscriptionId = null;
public static void main(String[] args) throws Exception {
try (DaprClient client = (new DaprClientBuilder()).build()) {
// Unsubscribe from config changes
UnsubscribeConfigurationResponse unsubscribe = client
.unsubscribeConfiguration(subscriptionId, DAPR_CONFIGURATON_STORE).block();
if (unsubscribe.getIsUnsubscribed()) {
System.out.println("App unsubscribed to config changes");
} else {
System.out.println("Error unsubscribing to config updates, err:" + unsubscribe.getMessage());
}
} catch (Exception e) {
System.out.println("Error unsubscribing to config updates," + e.getMessage());
System.exit(1);
}
}
```
{{% /codetab %}}
{{% codetab %}}
```python
#dependencies
import asyncio
import time
import logging
from dapr.clients import DaprClient
#code
async def executeConfiguration():
with DaprClient() as d:
CONFIG_STORE_NAME = 'configstore'
key = 'orderId'
# Subscribe to configuration by key.
configuration = await d.subscribe_configuration(store_name=CONFIG_STORE_NAME, keys=[key], config_metadata={})
if configuration != None:
items = configuration.get_items()
for item in items:
print(f"Subscribe key={item.key} value={item.value} version={item.version}", flush=True)
else:
print("Nothing yet")
asyncio.run(executeConfiguration())
```
subscriptionID = ""
with DaprClient() as d:
isSuccess = d.unsubscribe_configuration(store_name='configstore', id=subscriptionID)
print(f"Unsubscribed successfully? {isSuccess}", flush=True)
```
{{% /codetab %}}
{{% codetab %}}
```go
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"os"
"time"
dapr "github.com/dapr/go-sdk/client"
)
var DAPR_CONFIGURATION_STORE = "configstore"
var subscriptionID = ""
func main() {
client, err := dapr.NewClient()
if err != nil {
log.Panic(err)
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := client.UnsubscribeConfigurationItems(ctx, DAPR_CONFIGURATION_STORE , subscriptionID); err != nil {
panic(err)
}
}
```
{{% /codetab %}}
{{% codetab %}}
```js
import { CommunicationProtocolEnum, DaprClient } from "@dapr/dapr";
// JS SDK does not support Configuration API over HTTP protocol yet
const protocol = CommunicationProtocolEnum.GRPC;
const host = process.env.DAPR_HOST ?? "localhost";
const port = process.env.DAPR_GRPC_PORT ?? 3500;
const DAPR_CONFIGURATION_STORE = "configstore";
const CONFIGURATION_ITEMS = ["orderId1", "orderId2"];
async function main() {
const client = new DaprClient(host, port, protocol);
try {
const stream = await client.configuration.subscribeWithKeys(
DAPR_CONFIGURATION_STORE,
CONFIGURATION_ITEMS,
(config) => {
console.log("Configuration update", JSON.stringify(config.items));
}
);
setTimeout(() => {
// Unsubscribe to config updates
stream.stop();
console.log("App unsubscribed to config changes");
process.exit(0);
}, 20000);
} catch (error) {
console.log("Error subscribing to config updates, err:" + error);
process.exit(1);
}
}
main().catch((e) => console.error(e));
```
{{% /codetab %}}
{{% codetab %}}
```bash
dapr run --app-id orderprocessing --resources-path components/ -- python3 OrderProcessingService.py
curl 'http://localhost:<DAPR_HTTP_PORT>/v1.0/configuration/configstore/<subscription-id>/unsubscribe'
```
{{% /codetab %}}
{{% codetab %}}
```powershell
Invoke-RestMethod -Uri 'http://localhost:<DAPR_HTTP_PORT>/v1.0/configuration/configstore/<subscription-id>/unsubscribe'
```
{{% /codetab %}}
{{< /tabs >}}
#### Stop watching configuration items
After you've subscribed to watch configuration items, the gRPC-server stream starts. Since this stream thread does not close itself, you have to explicitly call the `UnSubscribeConfigurationRequest` API to unsubscribe. This method accepts the following request object:
```proto
// UnSubscribeConfigurationRequest is the message to stop watching the key-value configuration.
message UnSubscribeConfigurationRequest {
// The name of configuration store.
string store_name = 1;
// Optional. The keys of the configuration item to stop watching.
// Store_name and keys should match previous SubscribeConfigurationRequest's keys and store_name.
// Once invoked, the subscription that is watching update for the key-value event is stopped
repeated string keys = 2;
}
```
Using this unsubscribe method, you can stop watching configuration update events. Dapr locates the subscription stream based on the `store_name` and any optional keys supplied and closes it.
## Next steps
* Read [configuration API overview]({{< ref configuration-api-overview.md >}})
* Read [configuration API overview]({{< ref configuration-api-overview.md >}})

View File

@ -477,9 +477,15 @@ Some pub/sub brokers support sending and receiving multiple messages in a single
For components that do not have bulk publish or subscribe support, Dapr runtime uses the regular publish and subscribe APIs to send and receive messages one by one. This is still more efficient than directly using the regular publish or subscribe APIs, because applications can still send/receive multiple messages in a single request to/from Dapr.
## Watch the demo
## Demos
Watch [this video for an demo on bulk pub/sub](https://youtu.be/BxiKpEmchgQ?t=1170):
Watch the following demos and presentations about bulk pub/sub.
### [KubeCon Europe 2023 presentation](https://youtu.be/WMBAo-UNg6o)
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/WMBAo-UNg6o" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
### [Dapr Community Call #77 presentation](https://youtu.be/BxiKpEmchgQ?t=1170)
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/BxiKpEmchgQ?start=1170" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

View File

@ -11,39 +11,43 @@ To enable message routing and provide additional context with each message, Dapr
Dapr uses CloudEvents to provide additional context to the event payload, enabling features like:
- Tracing
- Deduplication by message Id
- Content-type for proper deserialization of event data
- Verification of sender application
## CloudEvents example
Dapr implements the following CloudEvents fields when creating a message topic.
A publish operation to Dapr results in a cloud event envelope containing the following fields:
- `id`
- `source`
- `specversion`
- `type`
- `traceparent`
- `traceid`
- `tracestate`
- `topic`
- `pubsubname`
- `time`
- `datacontenttype` (optional)
The following example demonstrates an `orders` topic message sent by Dapr that includes a W3C `traceid` unique to the message, the `data` and the fields for the CloudEvent where the data content is serialized as JSON.
The following example demonstrates a cloud event generated by Dapr for a publish operation to the `orders` topic that includes a W3C `traceid` unique to the message, the `data` and the fields for the CloudEvent where the data content is serialized as JSON.
```json
{
"topic": "orders",
"pubsubname": "order_pub_sub",
"traceid": "00-113ad9c4e42b27583ae98ba698d54255-e3743e35ff56f219-01",
"tracestate": "",
"data": {
"topic": "orders",
"pubsubname": "order_pub_sub",
"traceid": "00-113ad9c4e42b27583ae98ba698d54255-e3743e35ff56f219-01",
"tracestate": "",
"data": {
"orderId": 1
},
"id": "5929aaac-a5e2-4ca1-859c-edfe73f11565",
"specversion": "1.0",
"datacontenttype": "application/json; charset=utf-8",
"source": "checkout",
"type": "com.dapr.event.sent",
"time": "2020-09-23T06:23:21Z",
"traceparent": "00-113ad9c4e42b27583ae98ba698d54255-e3743e35ff56f219-01"
},
"id": "5929aaac-a5e2-4ca1-859c-edfe73f11565",
"specversion": "1.0",
"datacontenttype": "application/json; charset=utf-8",
"source": "checkout",
"type": "com.dapr.event.sent",
"time": "2020-09-23T06:23:21Z",
"traceparent": "00-113ad9c4e42b27583ae98ba698d54255-e3743e35ff56f219-01"
}
```
@ -65,6 +69,19 @@ As another example of a v1.0 CloudEvent, the following shows data as XML content
## Publish your own CloudEvent
If you want to use your own CloudEvent, make sure to specify the [`datacontenttype`]({{< ref "pubsub-overview.md#setting-message-content-types" >}}) as `application/cloudevents+json`.
If the CloudEvent that was authored by the app does not contain the [minimum required fields](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#required-attributes) in the CloudEvent specification, the message is rejected. Dapr adds the following fields to the CloudEvent if they are missing:
- `time`
- `traceid`
- `traceparent`
- `tracestate`
- `topic`
- `pubsubname`
- `source`
- `type`
- `specversion`
You can add additional fields to a custom CloudEvent that are not part of the official CloudEvent specification. Dapr will pass these fields as-is.
### Example
@ -102,6 +119,10 @@ Invoke-RestMethod -Method Post -ContentType 'application/cloudevents+json' -Body
{{< /tabs >}}
## Event deduplication
When using cloud events created by Dapr, the envelope contains an `id` field which can be used by the app to perform message deduplication. Dapr does not handle deduplication automatically. Dapr supports using message brokers that natively enable message deduplication.
## Next steps
- Learn why you might [not want to use CloudEvents]({{< ref pubsub-raw.md >}})

View File

@ -264,6 +264,96 @@ A workflow implementing the monitor pattern can loop forever or it can terminate
This pattern can also be expressed using actors and reminders. The difference is that this workflow is expressed as a single function with inputs and state stored in local variables. Workflows can also execute a sequence of actions with stronger reliability guarantees, if necessary.
{{% /alert %}}
## External system interaction
In some cases, a workflow may need to pause and wait for an external system to perform some action. For example, a workflow may need to pause and wait for a payment to be received. In this case, a payment system might publish an event to a pub/sub topic on receipt of a payment, and a listener on that topic can raise an event to the workflow using the [raise event workflow API]({{< ref "howto-manage-workflow.md#raise-an-event" >}}).
Another very common scenario is when a workflow needs to pause and wait for a human, for example when approving a purchase order. Dapr Workflow supports this event pattern via the [external events]({{< ref "workflow-features-concepts.md#external-events" >}}) feature.
Here's an example workflow for a purchase order involving a human:
1. A workflow is triggered when a purchase order is received.
1. A rule in the workflow determines that a human needs to perform some action. For example, the purchase order cost exceeds a certain auto-approval threshold.
1. The workflow sends a notification requesting a human action. For example, it sends an email with an approval link to a designated approver.
1. The workflow pauses and waits for the human to either approve or reject the order by clicking on a link.
1. If the approval isn't received within the specified time, the workflow resumes and performs some compensation logic, such as canceling the order.
The following diagram illustrates this flow.
<img src="/images/workflow-overview/workflow-human-interaction-pattern.png" width=600 alt="Diagram showing how the external system interaction pattern works with a human involved"/>
The following example code shows how this pattern can be implemented using Dapr Workflow.
{{< tabs ".NET" >}}
{{% codetab %}}
```csharp
public override async Task<OrderResult> RunAsync(WorkflowContext context, OrderPayload order)
{
// ...(other steps)...
// Require orders over a certain threshold to be approved
if (order.TotalCost > OrderApprovalThreshold)
{
try
{
// Request human approval for this order
await context.CallActivityAsync(nameof(RequestApprovalActivity), order);
// Pause and wait for a human to approve the order
ApprovalResult approvalResult = await context.WaitForExternalEventAsync<ApprovalResult>(
eventName: "ManagerApproval",
timeout: TimeSpan.FromDays(3));
if (approvalResult == ApprovalResult.Rejected)
{
// The order was rejected, end the workflow here
return new OrderResult(Processed: false);
}
}
catch (TaskCanceledException)
{
// An approval timeout results in automatic order cancellation
return new OrderResult(Processed: false);
}
}
// ...(other steps)...
// End the workflow with a success result
return new OrderResult(Processed: true);
}
```
{{% alert title="Note" color="primary" %}}
In the example above, `RequestApprovalActivity` is the name of a workflow activity to invoke and `ApprovalResult` is an enumeration defined by the workflow app. For brevity, these definitions were left out of the example code.
{{% /alert %}}
{{% /codetab %}}
{{< /tabs >}}
The code that delivers the event to resume the workflow execution is external to the workflow. Workflow events can be delivered to a waiting workflow instance using the [raise event]({{< ref "howto-manage-workflow.md#raise-an-event" >}}) workflow management API, as shown in the following example:
{{< tabs ".NET" >}}
{{% codetab %}}
```csharp
// Raise the workflow event to the waiting workflow
await daprClient.RaiseWorkflowEventAsync(
instanceId: orderId,
workflowComponent: "dapr",
eventName: "ManagerApproval",
eventData: ApprovalResult.Approved);
```
{{% /codetab %}}
{{< /tabs >}}
External events don't have to be directly triggered by humans. They can also be triggered by other systems. For example, a workflow may need to pause and wait for a payment to be received. In this case, a payment system might publish an event to a pub/sub topic on receipt of a payment, and a listener on that topic can raise an event to the workflow using the raise event workflow API.
## Next steps
{{< button text="Workflow architecture >>" page="workflow-architecture.md" >}}

View File

@ -8,43 +8,58 @@ aliases:
- /developing-applications/integrations/authenticating/authenticating-aws/
---
All Dapr components using various AWS services (DynamoDB, SQS, S3, etc) use a standardized set of attributes for configuration. See [how the AWS SDK (which Dapr uses) handles credentials](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials).
All Dapr components using various AWS services (DynamoDB, SQS, S3, etc) use a standardized set of attributes for configuration via the AWS SDK. [Learn more about how the AWS SDK handles credentials](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials).
None of the following attributes are required, since you can configure the AWS SDK using the default provider chain, described in the link above. Test the component configuration and inspect the log output from the Dapr runtime to ensure that components initialize correctly.
Since you can configure the AWS SDK using the default provider chain, all of the following attributes are optional. Test the component configuration and inspect the log output from the Dapr runtime to ensure that components initialize correctly.
| Attribute | Description |
| --------- | ----------- |
| `region` | Which AWS region to connect to. In some situations (when running Dapr in self-hosted mode, for example) this flag can be provided by the environment variable `AWS_REGION`. Since Dapr sidecar injection doesn't allow configuring environment variables on the Dapr sidecar, it is recommended to always set the `region` attribute in the component spec. |
| `region` | Which AWS region to connect to. In some situations (when running Dapr in self-hosted mode, for example), this flag can be provided by the environment variable `AWS_REGION`. Since Dapr sidecar injection doesn't allow configuring environment variables on the Dapr sidecar, it is recommended to always set the `region` attribute in the component spec. |
| `endpoint` | The endpoint is normally handled internally by the AWS SDK. However, in some situations it might make sense to set it locally - for example if developing against [DynamoDB Local](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.html). |
| `accessKey` | AWS Access key id. |
| `secretKey` | AWS Secret access key. Use together with `accessKey` to explicitly specify credentials. |
| `sessionToken` | AWS Session token. Used together with `accessKey` and `secretKey`. When using a regular IAM user's access key and secret, a session token is normally not required. |
{{% alert title="Important" color="warning" %}}
When running the Dapr sidecar (daprd) with your application on EKS (AWS Kubernetes), if you're using a node/pod that has already been attached to an IAM policy defining access to AWS resources, you **must not** provide AWS access-key, secret-key, and tokens in the definition of the component spec you're using.
You **must not** provide AWS access-key, secret-key, and tokens in the definition of the component spec you're using:
- When running the Dapr sidecar (`daprd`) with your application on EKS (AWS Kubernetes)
- If using a node/pod that has already been attached to an IAM policy defining access to AWS resources
{{% /alert %}}
## Alternatives to explicitly specifying credentials in component manifest files
In production scenarios, it is recommended to use a solution such as [Kiam](https://github.com/uswitch/kiam) or [Kube2iam](https://github.com/jtblin/kube2iam). If running on AWS EKS, you can [link an IAM role to a Kubernetes service account](https://docs.aws.amazon.com/eks/latest/userguide/create-service-account-iam-policy-and-role.html), which your pod can use.
In production scenarios, it is recommended to use a solution such as:
- [Kiam](https://github.com/uswitch/kiam)
- [Kube2iam](https://github.com/jtblin/kube2iam)
If running on AWS EKS, you can [link an IAM role to a Kubernetes service account](https://docs.aws.amazon.com/eks/latest/userguide/create-service-account-iam-policy-and-role.html), which your pod can use.
All of these solutions solve the same problem: They allow the Dapr runtime process (or sidecar) to retrive credentials dynamically, so that explicit credentials aren't needed. This provides several benefits, such as automated key rotation, and avoiding having to manage secrets.
Both Kiam and Kube2IAM work by intercepting calls to the [instance metadata service](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html).
## Using instance role/profile when running in stand-alone mode on AWS EC2
### Use an instance profile when running in stand-alone mode on AWS EC2
If running Dapr directly on an AWS EC2 instance in stand-alone mode, instance profiles can be used. Simply configure an iam role and [attach it to the instance profile](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html) for the ec2 instance, and Dapr should be able to authenticate to AWS without specifying credentials in the Dapr component manifest.
If running Dapr directly on an AWS EC2 instance in stand-alone mode, you can use instance profiles.
## Authenticating to AWS when running dapr locally in stand-alone mode
1. Configure an IAM role.
1. [Attach it to the instance profile](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html) for the ec2 instance.
When running Dapr (or the Dapr runtime directly) in stand-alone mode, you have the option of injecting environment variables into the process like this (on Linux/MacOS:
Dapr then authenticates to AWS without specifying credentials in the Dapr component manifest.
### Authenticate to AWS when running dapr locally in stand-alone mode
{{< tabs "Linux/MacOS" "Windows" >}}
<!-- linux -->
{{% codetab %}}
When running Dapr (or the Dapr runtime directly) in stand-alone mode, you can inject environment variables into the process, like the following example:
```bash
FOO=bar daprd --app-id myapp
```
If you have [configured named AWS profiles](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html) locally , you can tell Dapr (or the Dapr runtime) which profile to use by specifying the "AWS_PROFILE" environment variable:
If you have [configured named AWS profiles](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html) locally, you can tell Dapr (or the Dapr runtime) which profile to use by specifying the "AWS_PROFILE" environment variable:
```bash
AWS_PROFILE=myprofile dapr run...
@ -58,11 +73,27 @@ AWS_PROFILE=myprofile daprd...
You can use any of the [supported environment variables](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html#envvars-list) to configure Dapr in this manner.
On Windows, the environment variable needs to be set before starting the `dapr` or `daprd` command, doing it inline as shown above is not supported.
{{% /codetab %}}
## Authenticating to AWS if using AWS SSO based profiles
<!-- windows -->
{{% codetab %}}
If you authenticate to AWS using [AWS SSO](https://aws.amazon.com/single-sign-on/), some AWS SDKs (including the Go SDK) don't yet support this natively. There are several utilities you can use to "bridge the gap" between AWS SSO-based credentials, and "legacy" credentials, such as [AwsHelper](https://pypi.org/project/awshelper/) or [aws-sso-util](https://github.com/benkehoe/aws-sso-util).
On Windows, the environment variable needs to be set before starting the `dapr` or `daprd` command, doing it inline (like in Linux/MacOS) is not supported.
{{% /codetab %}}
{{< /tabs >}}
### Authenticate to AWS if using AWS SSO based profiles
If you authenticate to AWS using [AWS SSO](https://aws.amazon.com/single-sign-on/), some AWS SDKs (including the Go SDK) don't yet support this natively. There are several utilities you can use to "bridge the gap" between AWS SSO-based credentials and "legacy" credentials, such as:
- [AwsHelper](https://pypi.org/project/awshelper/)
- [aws-sso-util](https://github.com/benkehoe/aws-sso-util)
{{< tabs "Linux/MacOS" "Windows" >}}
<!-- linux -->
{{% codetab %}}
If using AwsHelper, start Dapr like this:
@ -75,7 +106,21 @@ or
```bash
AWS_PROFILE=myprofile awshelper daprd...
```
{{% /codetab %}}
On Windows, the environment variable needs to be set before starting the `awshelper` command, doing it inline as shown above is not supported.
<!-- windows -->
{{% codetab %}}
On Windows, the environment variable needs to be set before starting the `awshelper` command, doing it inline (like in Linxu/MacOS) is not supported.
{{% /codetab %}}
{{< /tabs >}}
## Next steps
{{< button text="Refer to AWS component specs >>" page="components-reference" >}}
## Related links
For more information, see [how the AWS SDK (which Dapr uses) handles credentials](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials).

View File

@ -67,6 +67,14 @@ You can also name each app directory's `.dapr` directory something other than `.
## Logs
The run template provides two log destination fields for each application and its associated daprd process:
1. `appLogDestination` : This field configures the log destination for the application. The possible values are `console`, `file` and `fileAndConsole`. The default value is `fileAndConsole` where application logs are written to both console and to a file by default.
2. `daprdLogDestination` : This field configures the log destination for the `daprd` process. The possible values are `console`, `file` and `fileAndConsole`. The default value is `file` where the `daprd` logs are written to a file by default.
#### Log file format
Logs for application and `daprd` are captured in separate files. These log files are created automatically under `.dapr/logs` directory under each application directory (`appDirPath` in the template). These log file names follow the pattern seen below:
- `<appID>_app_<timestamp>.log` (file name format for `app` log)
@ -74,6 +82,7 @@ Logs for application and `daprd` are captured in separate files. These log files
Even if you've decided to rename your resources folder to something other than `.dapr`, the log files are written only to the `.dapr/logs` folder (created in the application directory).
## Watch the demo
Watch [this video for an overview on Multi-App Run](https://youtu.be/s1p9MNl4VGo?t=2456):

View File

@ -7,13 +7,13 @@ description: Unpack the Multi-App Run template file and its properties
---
{{% alert title="Note" color="primary" %}}
Multi-App Run is currently a preview feature only supported in Linux/MacOS.
Multi-App Run is currently a preview feature only supported in Linux/MacOS.
{{% /alert %}}
The Multi-App Run template file is a YAML file that you can use to run multiple applications at once. In this guide, you'll learn how to:
- Use the multi-app template
- Use the multi-app template
- View started applications
- Stop the multi-app template
- Stop the multi-app template
- Stucture the multi-app template file
## Use the multi-app template
@ -65,7 +65,7 @@ dapr stop -f ./path/to/<your-preferred-file-name>.yaml
## Template file structure
The Multi-App Run template file can include the following properties. Below is an example template showing two applications that are configured with some of the properties.
The Multi-App Run template file can include the following properties. Below is an example template showing two applications that are configured with some of the properties.
```yaml
version: 1
@ -76,13 +76,17 @@ common: # optional section for variables shared across apps
apps:
- appID: webapp # optional
appDirPath: .dapr/webapp/ # REQUIRED
resourcesPath: .dapr/resources # (optional) can be default by convention
resourcesPath: .dapr/resources # deprecated
resourcesPaths: .dapr/resources # comma separated resources paths. (optional) can be left to default value by convention.
appChannelAddress: 127.0.0.1 # network address where the app listens on. (optional) can be left to default value by convention.
configFilePath: .dapr/config.yaml # (optional) can be default by convention too, ignore if file is not found.
appProtocol: http
appPort: 8080
appHealthCheckPath: "/healthz"
appHealthCheckPath: "/healthz"
command: ["python3" "app.py"]
- appID: backend # optional
appLogDestination: file # (optional), can be file, console or fileAndConsole. default is fileAndConsole.
daprdLogDestination: file # (optional), can be file, console or fileAndConsole. default is file.
- appID: backend # optional
appDirPath: .dapr/backend/ # REQUIRED
appProtocol: grpc
appPort: 3000
@ -103,14 +107,16 @@ The following rules apply for all the paths present in the template file:
## Template properties
The properties for the Multi-App Run template align with the `dapr run` CLI flags, [listed in the CLI reference documentation]({{< ref "dapr-run.md#flags" >}}).
The properties for the Multi-App Run template align with the `dapr run` CLI flags, [listed in the CLI reference documentation]({{< ref "dapr-run.md#flags" >}}).
| Properties | Required | Details | Example |
|--------------------------|:--------:|--------|---------|
| `appDirPath` | Y | Path to the your application code | `./webapp/`, `./backend/` |
| `appID` | N | Application's app ID. If not provided, will be derived from `appDirPath` | `webapp`, `backend` |
| `resourcesPath` | N | Path to your Dapr resources. Can be default by convention; ignore if directory isn't found | `./app/components`, `./webapp/components` |
| `resourcesPath` | N | **Deprecated**. Path to your Dapr resources. Can be default value by convention| `./app/components`, `./webapp/components` |
| `resourcesPaths` | N | Comma separated paths to your Dapr resources. Can be default value by convention | `./app/components`, `./webapp/components` |
| `appChannelAddress` | N | The network address the application listens on. Can be left to the default value by convention. | `127.0.0.1` | `localhost` |
| `configFilePath` | N | Path to your application's configuration file | `./webapp/config.yaml` |
| `appProtocol` | N | The protocol Dapr uses to talk to the application. | `http`, `grpc` |
| `appPort` | N | The port your application is listening on | `8080`, `3000` |
@ -137,6 +143,8 @@ The properties for the Multi-App Run template align with the `dapr run` CLI flag
| `enableApiLogging` | N | Enable the logging of all API calls from application to Dapr | |
| `runtimePath` | N | Dapr runtime install path | |
| `env` | N | Map to environment variable; environment variables applied per application will overwrite environment variables shared across applications | `DEBUG`, `DAPR_HOST_ADD` |
| `appLogDestination` | N | Log destination for outputting app logs; Its value can be file, console or fileAndConsole. Default is fileAndConsole | `file`, `console`, `fileAndConsole` |
| `daprdLogDestination` | N | Log destination for outputting daprd logs; Its value can be file, console or fileAndConsole. Default is file | `file`, `console`, `fileAndConsole` |
## Next steps

View File

@ -34,7 +34,7 @@ wget -q https://raw.githubusercontent.com/dapr/cli/master/install/install.sh -O
The following example shows how to install CLI version `{{% dapr-latest-version cli="true" %}}`. You can also install release candidates by specifying the version (for example, `1.10.0-rc.3`).
```bash
wget -q https://raw.githubusercontent.com/dapr/cli/master/install/install.sh -O - | /bin/bash -s 1.9.1
wget -q https://raw.githubusercontent.com/dapr/cli/master/install/install.sh -O - | /bin/bash -s {{% dapr-latest-version cli="true" %}}
```
@ -51,7 +51,7 @@ wget -q https://raw.githubusercontent.com/dapr/cli/master/install/install.sh -O
The following example shows how to install CLI version `{{% dapr-latest-version cli="true" %}}`. You can also install release candidates by specifying the version (for example, `1.10.0-rc.3`).
```bash
wget -q https://raw.githubusercontent.com/dapr/cli/master/install/install.sh -O - | DAPR_INSTALL_DIR="$HOME/dapr" /bin/bash -s 1.9.1
wget -q https://raw.githubusercontent.com/dapr/cli/master/install/install.sh -O - | DAPR_INSTALL_DIR="$HOME/dapr" /bin/bash -s {{% dapr-latest-version cli="true" %}}
```
{{% /codetab %}}
@ -73,7 +73,7 @@ powershell -Command "iwr -useb https://raw.githubusercontent.com/dapr/cli/master
The following example shows how to install CLI version `{{% dapr-latest-version cli="true" %}}`. You can also install release candidates by specifying the version (for example, `1.10.0-rc.3`).
```powershell
powershell -Command "$script=iwr -useb https://raw.githubusercontent.com/dapr/cli/master/install/install.ps1; $block=[ScriptBlock]::Create($script); invoke-command -ScriptBlock $block -ArgumentList 1.9.1"
powershell -Command "$script=iwr -useb https://raw.githubusercontent.com/dapr/cli/master/install/install.ps1; $block=[ScriptBlock]::Create($script); invoke-command -ScriptBlock $block -ArgumentList {{% dapr-latest-version cli="true" %}}"
```
#### Install without administrative rights
@ -91,7 +91,7 @@ The following example shows how to install CLI version `{{% dapr-latest-version
```powershell
$Env:DAPR_INSTALL_DIR = "<your_alt_install_dir_path>"
$script=iwr -useb https://raw.githubusercontent.com/dapr/cli/master/install/install.ps1; $block=[ScriptBlock]::Create($script); invoke-command -ScriptBlock $block -ArgumentList "1.9.1", "$Env:DAPR_INSTALL_DIR"
$script=iwr -useb https://raw.githubusercontent.com/dapr/cli/master/install/install.ps1; $block=[ScriptBlock]::Create($script); invoke-command -ScriptBlock $block -ArgumentList "{{% dapr-latest-version cli="true" %}}", "$Env:DAPR_INSTALL_DIR"
```
#### Install using winget
@ -136,7 +136,7 @@ curl -fsSL https://raw.githubusercontent.com/dapr/cli/master/install/install.sh
The following example shows how to install CLI version `{{% dapr-latest-version cli="true" %}}`. You can also install release candidates by specifying the version (for example, `1.10.0-rc.3`).
```bash
curl -fsSL https://raw.githubusercontent.com/dapr/cli/master/install/install.sh | /bin/bash -s 1.9.1
curl -fsSL https://raw.githubusercontent.com/dapr/cli/master/install/install.sh | /bin/bash -s {{% dapr-latest-version cli="true" %}}
```
**For ARM64 Macs:**
@ -177,7 +177,7 @@ curl -fsSL https://raw.githubusercontent.com/dapr/cli/master/install/install.sh
The following example shows how to install CLI version `{{% dapr-latest-version cli="true" %}}`. You can also install release candidates by specifying the version (for example, `1.10.0-rc.3`).
```bash
curl -fsSL https://raw.githubusercontent.com/dapr/cli/master/install/install.sh | DAPR_INSTALL_DIR="$HOME/dapr" -s 1.9.1
curl -fsSL https://raw.githubusercontent.com/dapr/cli/master/install/install.sh | DAPR_INSTALL_DIR="$HOME/dapr" -s {{% dapr-latest-version cli="true" %}}
```
{{% /codetab %}}

View File

@ -26,6 +26,7 @@ Hit the ground running with our Dapr quickstarts, complete with code samples aim
| [Service Invocation]({{< ref serviceinvocation-quickstart.md >}}) | Synchronous communication between two services using HTTP or gRPC. |
| [State Management]({{< ref statemanagement-quickstart.md >}}) | Store a service's data as key/value pairs in supported state stores. |
| [Bindings]({{< ref bindings-quickstart.md >}}) | Work with external systems using input bindings to respond to events and output bindings to call operations. |
| [Actors]({{< ref actors-quickstart.md >}}) | Run a microservice and a simple console client to demonstrate stateful object patterns in Dapr Actors. |
| [Secrets Management]({{< ref secrets-quickstart.md >}}) | Securely fetch secrets. |
| [Configuration]({{< ref configuration-quickstart.md >}}) | Get configuration items and subscribe for configuration updates. |
| [Resiliency]({{< ref resiliency >}}) | Define and apply fault-tolerance policies to your Dapr API requests. |

View File

@ -0,0 +1,257 @@
---
type: docs
title: "Quickstart: Actors"
linkTitle: "Actors"
weight: 75
description: "Get started with Dapr's Actors building block"
---
Let's take a look at Dapr's [Actors building block]({{< ref actors >}}). In this Quickstart, you will run a smart device microservice and a simple console client to demonstrate the stateful object patterns in Dapr Actors.
Currently, you can experience this actors quickstart using the .NET SDK.
{{< tabs ".NET" >}}
<!-- .NET -->
{{% codetab %}}
As a quick overview of the .NET actors quickstart:
1. Using a `SmartDevice.Service` microservice, you host:
- Two `SmartDectectorActor` smoke alarm objects
- A `ControllerActor` object that commands and controls the smart devices
1. Using a `SmartDevice.Client` console app, the client app interacts with each actor, or the controller, to perform actions in aggregate.
1. The `SmartDevice.Interfaces` contains the shared interfaces and data types used by both the service and client apps.
<img src="/images/actors-quickstart/actors-quickstart.png" width=800 style="padding-bottom:15px;">
### Pre-requisites
For this example, you will need:
- [Dapr CLI and initialized environment](https://docs.dapr.io/getting-started).
- [.NET SDK or .NET 6 SDK installed](https://dotnet.microsoft.com/download).
<!-- IGNORE_LINKS -->
- [Docker Desktop](https://www.docker.com/products/docker-desktop)
<!-- END_IGNORE -->
### Step 1: Set up the environment
Clone the [sample provided in the Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/actors).
```bash
git clone https://github.com/dapr/quickstarts.git
```
### Step 2: Run the service app
In a new terminal window, navigate to the `actors/csharp/sdk/service` directory and restore dependencies:
```bash
cd actors/csharp/sdk/service
dotnet build
```
Run the `SmartDevice.Service`, which will start service itself and the Dapr sidecar:
```bash
dapr run --app-id actorservice --app-port 5001 --dapr-http-port 3500 --resources-path ../../../resources -- dotnet run --urls=http://localhost:5001/
```
Expected output:
```bash
== APP == info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
== APP == Request starting HTTP/1.1 GET http://127.0.0.1:5001/healthz - -
== APP == info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
== APP == Executing endpoint 'Dapr Actors Health Check'
== APP == info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
== APP == Executed endpoint 'Dapr Actors Health Check'
== APP == info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
== APP == Request finished HTTP/1.1 GET http://127.0.0.1:5001/healthz - - - 200 - text/plain 5.2599ms
```
### Step 3: Run the client app
In a new terminal instance, navigate to the `actors/csharp/sdk/client` directory and install the dependencies:
```bash
cd ./actors/csharp/sdk/client
dotnet build
```
Run the `SmartDevice.Client` app:
```bash
dapr run --app-id actorclient -- dotnet run
```
Expected output:
```bash
== APP == Startup up...
== APP == Calling SetDataAsync on SmokeDetectorActor:1...
== APP == Got response: Success
== APP == Calling GetDataAsync on SmokeDetectorActor:1...
== APP == Device 1 state: Location: First Floor, Status: Ready
== APP == Calling SetDataAsync on SmokeDetectorActor:2...
== APP == Got response: Success
== APP == Calling GetDataAsync on SmokeDetectorActor:2...
== APP == Device 2 state: Location: Second Floor, Status: Ready
== APP == Registering the IDs of both Devices...
== APP == Registered devices: 1, 2
== APP == Detecting smoke on Device 1...
== APP == Device 1 state: Location: First Floor, Status: Alarm
== APP == Device 2 state: Location: Second Floor, Status: Alarm
== APP == Sleeping for 16 seconds before checking status again to see reminders fire and clear alarms
== APP == Device 1 state: Location: First Floor, Status: Ready
== APP == Device 2 state: Location: Second Floor, Status: Ready
```
### (Optional) Step 4: View in Zipkin
If you have Zipkin configured for Dapr locally on your machine, you can view the actor's interaction with the client in the Zipkin web UI (typically at `http://localhost:9411/zipkin/`).
<img src="/images/actors-quickstart/actor-client-interaction-zipkin.png" width=800 style="padding-bottom:15px;">
### What happened?
When you ran the client app, a few things happened:
1. Two `SmartDetectorActor` actors were [created in the client application](https://github.com/dapr/quickstarts/blob/master/actors/csharp/sdk/client/Program.cs) and initialized with object state with:
- `ActorProxy.Create<ISmartDevice>(actorId, actorType)`
- `proxySmartDevice.SetDataAsync(data)`
These objects are re-entrant and hold the state, as shown by `proxySmartDevice.GetDataAsync()`.
```csharp
// Actor Ids and types
var deviceId1 = "1";
var deviceId2 = "2";
var smokeDetectorActorType = "SmokeDetectorActor";
var controllerActorType = "ControllerActor";
Console.WriteLine("Startup up...");
// An ActorId uniquely identifies the first actor instance for the first device
var deviceActorId1 = new ActorId(deviceId1);
// Create a new instance of the data class that will be stored in the first actor
var deviceData1 = new SmartDeviceData(){
Location = "First Floor",
Status = "Ready",
};
// Create the local proxy by using the same interface that the service implements.
var proxySmartDevice1 = ActorProxy.Create<ISmartDevice>(deviceActorId1, smokeDetectorActorType);
// Now you can use the actor interface to call the actor's methods.
Console.WriteLine($"Calling SetDataAsync on {smokeDetectorActorType}:{deviceActorId1}...");
var setDataResponse1 = await proxySmartDevice1.SetDataAsync(deviceData1);
Console.WriteLine($"Got response: {setDataResponse1}");
Console.WriteLine($"Calling GetDataAsync on {smokeDetectorActorType}:{deviceActorId1}...");
var storedDeviceData1 = await proxySmartDevice1.GetDataAsync();
Console.WriteLine($"Device 1 state: {storedDeviceData1}");
// Create a second actor for second device
var deviceActorId2 = new ActorId(deviceId2);
// Create a new instance of the data class that will be stored in the first actor
var deviceData2 = new SmartDeviceData(){
Location = "Second Floor",
Status = "Ready",
};
// Create the local proxy by using the same interface that the service implements.
var proxySmartDevice2 = ActorProxy.Create<ISmartDevice>(deviceActorId2, smokeDetectorActorType);
// Now you can use the actor interface to call the second actor's methods.
Console.WriteLine($"Calling SetDataAsync on {smokeDetectorActorType}:{deviceActorId2}...");
var setDataResponse2 = await proxySmartDevice2.SetDataAsync(deviceData2);
Console.WriteLine($"Got response: {setDataResponse2}");
Console.WriteLine($"Calling GetDataAsync on {smokeDetectorActorType}:{deviceActorId2}...");
var storedDeviceData2 = await proxySmartDevice2.GetDataAsync();
Console.WriteLine($"Device 2 state: {storedDeviceData2}");
```
1. The [`DetectSmokeAsync` method of `SmartDetectorActor 1` is called](https://github.com/dapr/quickstarts/blob/master/actors/csharp/sdk/service/SmokeDetectorActor.cs#L70).
```csharp
public async Task DetectSmokeAsync()
{
var controllerActorId = new ActorId("controller");
var controllerActorType = "ControllerActor";
var controllerProxy = ProxyFactory.CreateActorProxy<IController>(controllerActorId, controllerActorType);
await controllerProxy.TriggerAlarmForAllDetectors();
}
```
1. The [`TriggerAlarmForAllDetectors` method of `ControllerActor` is called](https://github.com/dapr/quickstarts/blob/master/actors/csharp/sdk/service/ControllerActor.cs#L54). The `ControllerActor` internally triggers all alarms when smoke is detected
```csharp
public async Task TriggerAlarmForAllDetectors()
{
var deviceIds = await ListRegisteredDeviceIdsAsync();
foreach (var deviceId in deviceIds)
{
var actorId = new ActorId(deviceId);
var proxySmartDevice = ProxyFactory.CreateActorProxy<ISmartDevice>(actorId, "SmokeDetectorActor");
await proxySmartDevice.SoundAlarm();
}
// Register a reminder to refresh and clear alarm state every 15 seconds
await this.RegisterReminderAsync("AlarmRefreshReminder", null, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
}
```
The console [prints a message indicating that smoke has been detected](https://github.com/dapr/quickstarts/blob/master/actors/csharp/sdk/client/Program.cs#L65).
```csharp
// Smoke is detected on device 1 that triggers an alarm on all devices.
Console.WriteLine($"Detecting smoke on Device 1...");
proxySmartDevice1 = ActorProxy.Create<ISmartDevice>(deviceActorId1, smokeDetectorActorType);
await proxySmartDevice1.DetectSmokeAsync();
```
1. The [`SoundAlarm` methods](https://github.com/dapr/quickstarts/blob/master/actors/csharp/sdk/service/SmokeDetectorActor.cs#L78) of `SmartDetectorActor 1` and `2` are called.
```csharp
storedDeviceData1 = await proxySmartDevice1.GetDataAsync();
Console.WriteLine($"Device 1 state: {storedDeviceData1}");
storedDeviceData2 = await proxySmartDevice2.GetDataAsync();
Console.WriteLine($"Device 2 state: {storedDeviceData2}");
```
1. The `ControllerActor` also creates a durable reminder to call `ClearAlarm` after 15 seconds using `RegisterReminderAsync`.
```csharp
// Register a reminder to refresh and clear alarm state every 15 seconds
await this.RegisterReminderAsync("AlarmRefreshReminder", null, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
```
For full context of the sample, take a look at the following code:
- [`SmartDetectorActor.cs`](https://github.com/dapr/quickstarts/blob/master/actors/csharp/sdk/service/SmokeDetectorActor.cs): Implements the smart device actors
- [`ControllerActor.cs`](https://github.com/dapr/quickstarts/blob/master/actors/csharp/sdk/service/ControllerActor.cs): Implements the controller actor that manages all devices
- [`ISmartDevice`](https://github.com/dapr/quickstarts/blob/master/actors/csharp/sdk/interfaces/ISmartDevice.cs): The method definitions and shared data types for each `SmartDetectorActor`
- [`IController`](https://github.com/dapr/quickstarts/blob/master/actors/csharp/sdk/interfaces/IController.cs): The method definitions and shared data types for the `ControllerActor`
{{% /codetab %}}
{{< /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).
## Next steps
Learn more about [the Actor building block]({{< ref actors >}})
{{< button text="Explore Dapr tutorials >>" page="getting-started/tutorials/_index.md" >}}

View File

@ -2,7 +2,7 @@
type: docs
title: "Quickstart: Configuration"
linkTitle: Configuration
weight: 76
weight: 77
description: Get started with Dapr's Configuration building block
---
@ -620,6 +620,12 @@ case <-ctx.Done():
{{< /tabs >}}
## Demo
Watch this video [demoing the Configuration API quickstart](https://youtu.be/EcE6IGuX9L8?t=94):
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/EcE6IGuX9L8?start=94" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
## 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?

View File

@ -2,7 +2,7 @@
type: docs
title: "Quickstart: Secrets Management"
linkTitle: "Secrets Management"
weight: 75
weight: 76
description: "Get started with Dapr's Secrets Management building block"
---

View File

@ -180,12 +180,12 @@ The `order-processor` service writes, reads, and deletes an `orderId` key/value
const client = new DaprClient()
// Save state into a state store
await client.state.save(DAPR_STATE_STORE_NAME, state)
await client.state.save(DAPR_STATE_STORE_NAME, order)
console.log("Saving Order: ", order)
// Get state from a state store
const savedOrder = await client.state.get(DAPR_STATE_STORE_NAME, order.orderId)
console.log("Getting Order: ", savedOrd)
console.log("Getting Order: ", savedOrder)
// Delete state from the state store
await client.state.delete(DAPR_STATE_STORE_NAME, order.orderId)

View File

@ -2,7 +2,7 @@
type: docs
title: "Quickstart: Workflow"
linkTitle: Workflow
weight: 77
weight: 78
description: Get started with the Dapr Workflow building block
---

View File

@ -16,17 +16,7 @@ In this tutorial, you will create a component definition file to interact with t
## Step 1: Create a JSON secret store
Dapr supports [many types of secret stores]({{< ref supported-secret-stores >}}), but for this tutorial, create a local JSON file named `mysecrets.json` with the following secret:
```json
{
"my-secret" : "I'm Batman"
}
```
## Step 2: Create a secret store Dapr component
1. Create a new directory named `my-components` to hold the new component file:
1. Create a new directory named `my-components` to hold the new secret and component file:
```bash
mkdir my-components
@ -38,6 +28,16 @@ Dapr supports [many types of secret stores]({{< ref supported-secret-stores >}})
cd my-components
```
1. Dapr supports [many types of secret stores]({{< ref supported-secret-stores >}}), but for this tutorial, create a local JSON file named `mysecrets.json` with the following secret:
```json
{
"my-secret" : "I'm Batman"
}
```
## Step 2: Create a secret store Dapr component
1. Create a new file `localSecretStore.yaml` with the following contents:
```yaml
@ -51,13 +51,13 @@ Dapr supports [many types of secret stores]({{< ref supported-secret-stores >}})
version: v1
metadata:
- name: secretsFile
value: <PATH TO SECRETS FILE>/mysecrets.json
value: ./mysecrets.json
- name: nestedSeparator
value: ":"
```
In the above file definition:
- `type: secretstores.local.file` tells Dapr to use the local file component as a secret store.
- `type: secretstores.local.file` tells Dapr to use the local file component as a secret store.
- The metadata fields provide component-specific information needed to work with this component. In this case, the secret store JSON path is relative to where you call `dapr run`.
## Step 3: Run the Dapr sidecar
@ -65,7 +65,7 @@ In the above file definition:
Launch a Dapr sidecar that will listen on port 3500 for a blank application named `myapp`:
```bash
dapr run --app-id myapp --dapr-http-port 3500 --resources-path ./my-components
dapr run --app-id myapp --dapr-http-port 3500 --resources-path .
```
{{% alert title="Tip" color="primary" %}}
@ -104,4 +104,4 @@ Invoke-RestMethod -Uri 'http://localhost:3500/v1.0/secrets/my-secret-store/my-se
{"my-secret":"I'm Batman"}
```
{{< button text="Next step: Set up a Pub/sub broker >>" page="pubsub-quickstart" >}}
{{< button text="Next step: Set up a Pub/sub broker >>" page="pubsub-quickstart" >}}

View File

@ -0,0 +1,63 @@
---
type: docs
title: "Breaking changes and deprecations"
linkTitle: "Breaking changes and deprecations"
weight: 2500
description: "Handling of breaking changes and deprecations"
---
## Breaking changes
Breaking changes are defined as a change to any of the following that cause compilation errors or undesirable runtime behavior to an existing 3rd party consumer application or script after upgrading to the next stable minor version of a Dapr artifact (SDK, CLI, runtime, etc):
- Code behavior
- Schema
- Default configuration value
- Command line argument
- Published metric
- Kubernetes CRD template
- Publicly accessible API
- Publicly visible SDK interface, method, class, or attribute
Breaking changes can be applied right away to the following cases:
- Projects versioned at 0.x.y
- Preview feature
- Alpha API
- Preview or Alpha interface, class, method or attribute in SDK
- Dapr Component in Alpha or Beta
- Components-Contrib interface
- URLs in Docs and Blog
- An **exceptional** case where it is **required** to fix a critical bug or security vulnerability.
### Process for applying breaking changes
There is a process for applying breaking changes:
1. A deprecation notice must be posted as part of a release.
1. The breaking changes are applied two (2) releases after the release in which the deprecation was announced.
- For example, feature X is announced to be deprecated in the 1.0.0 release notes and will then be removed in 1.2.0.
## Deprecations
Deprecations appear in release notes under a section named “Deprecations”, which indicates:
- The point in the future the now-deprecated feature will no longer be supported. For example release x.y.z. This is at least two (2) releases prior.
- Document any steps the user must take to modify their code, operations, etc if applicable in the release notes.
After announcing a future breaking change, the change will happen in 2 releases or 6 months, whichever is greater. Deprecated features should respond with warning but do nothing otherwise.
## Announced deprecations
| Feature | Deprecation announcement | Removal |
|-----------------------|-----------------------|------------------------- |
| GET /v1.0/shutdown API (Users should use [POST API]({{< ref kubernetes-job.md >}}) instead) | 1.2.0 | 1.4.0 |
| Java domain builder classes deprecated (Users should use [setters](https://github.com/dapr/java-sdk/issues/587) instead) | Java SDK 1.3.0 | Java SDK 1.5.0 |
| Service invocation will no longer provide a default content type header of `application/json` when no content-type is specified. You must explicitly [set a content-type header]({{< ref "service_invocation_api.md#request-contents" >}}) for service invocation if your invoked apps rely on this header. | 1.7.0 | 1.9.0 |
| gRPC service invocation using `invoke` method is deprecated. Use proxy mode service invocation instead. See [How-To: Invoke services using gRPC ]({{< ref howto-invoke-services-grpc.md >}}) to use the proxy mode.| 1.9.0 | 1.10.0 |
## Related links
- Read the [Versioning Policy]({{< ref support-versioning.md >}})
- Read the [Supported Releases]({{< ref support-release-policy.md >}})

View File

@ -22,6 +22,7 @@ For CLI there is no explicit opt-in, just the version that this was first made a
| **Workflows** | Author workflows as code to automate and orchestrate tasks within your application, like messaging, state management, and failure handling | N/A | [Workflows concept]({{< ref "components-concept#workflows" >}})| v1.10 |
| **Cryptography** | Encrypt or decrypt data without having to manage secrets keys | N/A | [Cryptography concept]({{< ref "components-concept#cryptography" >}})| v1.11 |
| **Service invocation for non-Dapr endpoints** | Allow the invocation of non-Dapr endpoints by Dapr using the [Service invocation API]({{< ref service_invocation_api.md >}}). Read ["How-To: Invoke Non-Dapr Endpoints using HTTP"]({{< ref howto-invoke-non-dapr-endpoints.md >}}) for more information. | N/A | [Service invocation API]({{< ref service_invocation_api.md >}}) | v1.11 |
| **Actor State TTL** | Allow actors to save records to state stores with Time To Live (TTL) set to automatically clean up old data. In its current implementation, actor state with TTL may not be reflected correctly by clients, read [Actor State Transactions]({{< ref actors_api.md >}}) for more information. | `ActorStateTTL` | [Actor State Transactions]({{< ref actors_api.md >}}) | v1.11 |
### Streaming for HTTP service invocation
@ -44,7 +45,7 @@ Important notes:
- `ServiceInvocationStreaming` needs to be applied on caller sidecars only.
In the example above, streams are used for HTTP service invocation if `ServiceInvocationStreaming` is applied to the configuration of "app A" and its Dapr sidecar, regardless of whether the feature flag is enabled for "app B" and its sidecar.
- When `ServiceInvocationStreaming` is enabled, you should make sure that all services your app invokes using Dapr ("app B") are updated to Dapr 1.10, even if `ServiceInvocationStreaming` is not enabled for those sidecars.
Invoking an app using Dapr 1.9 or older is still possible, but those calls may fail if you have applied a Dapr Resiliency policy with retries enabled.
- When `ServiceInvocationStreaming` is enabled, you should make sure that all services your app invokes using Dapr ("app B") are updated to Dapr 1.10 or higher, even if `ServiceInvocationStreaming` is not enabled for those sidecars.
Invoking an app using Dapr 1.9 or older is still possible, but those calls may fail unless you have applied a Dapr Resiliency policy with retries enabled.
> Full support for streaming for HTTP service invocation will be completed in a future Dapr version.

View File

@ -28,13 +28,26 @@ There will be at least 6 weeks between major.minor version releases giving users
Patch support is for supported versions (current and previous).
## Build variations
The Dapr's sidecar image is published to both [GitHub Container Registry](https://github.com/dapr/dapr/pkgs/container/daprd) and [Docker Registry](https://hub.docker.com/r/daprio/daprd/tags). The default image contains all components. From version 1.11, Dapr also offers a variation of the sidecar image, containing only stable components.
* Default sidecar images: `daprio/daprd:<version>` or `ghcr.io/dapr/daprd:<version>` (for example `ghcr.io/dapr/daprd:1.11.0`)
* Sidecar images for stable components: `daprio/daprd:<version>-stable` or `ghcr.io/dapr/daprd:<version>-stable` (for example `ghcr.io/dapr/daprd:1.11.0-stable`)
On Kubernetes, the sidecar image can be overwritten for the application Deployment resource with the `dapr.io/sidecar-image` annotation. See more about [Dapr's arguments and annotations]({{<ref "arguments-annotations-overview.md" >}}). The default 'daprio/daprd:latest' image is used if not specified.
Learn more about [Dapr components' certification lifecycle]({{<ref "certification-lifecycle.md" >}}).
## Supported versions
The table below shows the versions of Dapr releases that have been tested together and form a "packaged" release. Any other combinations of releases are not supported.
| Release date | Runtime | CLI | SDKs | Dashboard | Status |
|--------------------|:--------:|:--------|---------|---------|---------|
| April 13 2023 | 1.10.5</br> | 1.10.0 | Java 1.8.0 </br>Go 1.6.0 </br>PHP 1.1.0 </br>Python 1.9.0 </br>.NET 1.10.0 </br>JS 2.5.0 | 0.11.0 | Supported (current) |
| May 15th 2023 | 1.10.7</br> | 1.10.0 | Java 1.8.0 </br>Go 1.6.0 </br>PHP 1.1.0 </br>Python 1.9.0 </br>.NET 1.10.0 </br>JS 2.5.0 | 0.11.0 | Supported (current) |
| May 12th 2023 | 1.10.6</br> | 1.10.0 | Java 1.8.0 </br>Go 1.6.0 </br>PHP 1.1.0 </br>Python 1.9.0 </br>.NET 1.10.0 </br>JS 2.5.0 | 0.11.0 | Supported (current) |
| April 13 2023 |1.10.5</br> | 1.10.0 | Java 1.8.0 </br>Go 1.6.0 </br>PHP 1.1.0 </br>Python 1.9.0 </br>.NET 1.10.0 </br>JS 2.5.0 | 0.11.0 | Supported (current) |
| March 16 2023 | 1.10.4</br> | 1.10.0 | Java 1.8.0 </br>Go 1.6.0 </br>PHP 1.1.0 </br>Python 1.9.0 </br>.NET 1.10.0 </br>JS 2.5.0 | 0.11.0 | Supported |
| March 14 2023 | 1.10.3</br> | 1.10.0 | Java 1.8.0 </br>Go 1.6.0 </br>PHP 1.1.0 </br>Python 1.9.0 </br>.NET 1.10.0 </br>JS 2.5.0 | 0.11.0 | Supported |
| February 24 2023 | 1.10.2</br> | 1.10.0 | Java 1.8.0 </br>Go 1.6.0 </br>PHP 1.1.0 </br>Python 1.9.0 </br>.NET 1.10.0 </br>JS 2.5.0 | 0.11.0 | Supported |
@ -92,70 +105,17 @@ General guidance on upgrading can be found for [self hosted mode]({{< ref self-h
| | 1.6.2 | 1.7.5 |
| | 1.7.5 | 1.8.6 |
| | 1.8.6 | 1.9.6 |
| | 1.9.6 | 1.10.5 |
| | 1.9.6 | 1.10.7 |
| 1.6.0 to 1.6.2 | N/A | 1.7.5 |
| | 1.7.5 | 1.8.6 |
| | 1.8.6 | 1.9.6 |
| | 1.9.6 | 1.10.5 |
| | 1.9.6 | 1.10.7 |
| 1.7.0 to 1.7.5 | N/A | 1.8.6 |
| | 1.8.6 | 1.9.6 |
| | 1.9.6 | 1.10.5 |
| | 1.9.6 | 1.10.7 |
| 1.8.0 to 1.8.6 | N/A | 1.9.6 |
| 1.9.0 | N/A | 1.9.6 |
| 1.10.0 | N/A | 1.10.5 |
## Breaking changes and deprecations
### Breaking changes
Breaking changes are defined as a change to any of the following that cause compilation errors or undesirable runtime behavior to an existing 3rd party consumer application or script after upgrading to the next stable minor version of a Dapr artifact (SDK, CLI, runtime, etc):
- Code behavior
- Schema
- Default configuration value
- Command line argument
- Published metric
- Kubernetes CRD template
- Publicly accessible API
- Publicly visible SDK interface, method, class, or attribute
Breaking changes can be applied right away to the following cases:
- Projects versioned at 0.x.y
- Preview feature
- Alpha API
- Preview or Alpha interface, class, method or attribute in SDK
- Dapr Component in Alpha or Beta
- Components-Contrib interface
- URLs in Docs and Blog
- An **exceptional** case where it is **required** to fix a critical bug or security vulnerability.
#### Process for applying breaking changes
There is a process for applying breaking changes:
1. A deprecation notice must be posted as part of a release.
1. The breaking changes are applied two (2) releases after the release in which the deprecation was announced.
- For example, feature X is announced to be deprecated in the 1.0.0 release notes and will then be removed in 1.2.0.
### Depreciations
Deprecations appear in release notes under a section named “Deprecations”, which indicates:
- The point in the future the now-deprecated feature will no longer be supported. For example release x.y.z. This is at least two (2) releases prior.
- Document any steps the user must take to modify their code, operations, etc if applicable in the release notes.
After announcing a future breaking change, the change will happen in 2 releases or 6 months, whichever is greater. Deprecated features should respond with warning but do nothing otherwise.
### Announced deprecations
| Feature | Deprecation announcement | Removal |
|-----------------------|-----------------------|------------------------- |
| GET /v1.0/shutdown API (Users should use [POST API]({{< ref kubernetes-job.md >}}) instead) | 1.2.0 | 1.4.0 |
| Java domain builder classes deprecated (Users should use [setters](https://github.com/dapr/java-sdk/issues/587) instead) | Java SDK 1.3.0 | Java SDK 1.5.0 |
| Service invocation will no longer provide a default content type header of `application/json` when no content-type is specified. You must explicitly [set a content-type header]({{< ref "service_invocation_api.md#request-contents" >}}) for service invocation if your invoked apps rely on this header. | 1.7.0 | 1.9.0 |
| gRPC service invocation using `invoke` method is deprecated. Use proxy mode service invocation instead. See [How-To: Invoke services using gRPC ]({{< ref howto-invoke-services-grpc.md >}}) to use the proxy mode.| 1.9.0 | 1.10.0 |
| 1.10.0 | N/A | 1.10.7 |
## Upgrade on Hosting platforms
@ -173,4 +133,5 @@ Below is a list of software that the latest version of Dapr (v{{% dapr-latest-ve
## Related links
- Read the [Versioning policy]({{< ref support-versioning.md >}})
- Read the [Versioning Policy]({{< ref support-versioning.md >}})
- Read the [Breaking Changes and Deprecation Policy]({{< ref breaking-changes-and-deprecations.md >}})

View File

@ -75,10 +75,15 @@ Persists the change to the state for an actor as a multi-item transaction.
***Note that this operation is dependant on a using state store component that supports multi-item transactions.***
When putting state, _always_ set the `ttlInSeconds` field in the
metadata for each value, unless there is a state clean up process out of band of
Dapr. Omitting this field will result in the underlying Actor state store to
grow indefinitely.
#### TTL
With the [`ActorStateTTL` feature enabled]]({{< ref
"support-preview-features.md" >}}), actor clients can set the `ttlInSeconds`
field in the transaction metadata to have the state expire after that many
seconds. If the `ttlInSeconds` field is not set, the state will not expire.
Keep in mind when building actor applications with this feature enabled;
Currently, all actor SDKs will preserve the actor state in their local cache even after the state has expired. This means that the actor state will not be removed from the local cache if the TTL has expired until the actor is restarted or deactivated. This behaviour will be changed in a future release.
See the Dapr Community Call 80 recording for more details on actor state TTL.
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/kVpQYkGemRc?start=28" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
@ -109,6 +114,8 @@ Parameter | Description
#### Examples
> Note, the following example uses the `ttlInSeconds` field, which requires the [`ActorStateTTL` feature enabled]]({{< ref "support-preview-features.md" >}}).
```shell
curl -X POST http://localhost:3500/v1.0/actors/stormtrooper/50/state \
-H "Content-Type: application/json" \

View File

@ -13,7 +13,7 @@ This endpoint lets you get configuration from a store.
### HTTP Request
```
GET http://localhost:<daprPort>/v1.0-alpha1/configuration/<storename>
GET http://localhost:<daprPort>/v1.0/configuration/<storename>
```
#### URL Parameters
@ -29,13 +29,13 @@ If no query parameters are provided, all configuration items are returned.
To specify the keys of the configuration items to get, use one or more `key` query parameters. For example:
```
GET http://localhost:<daprPort>/v1.0-alpha1/configuration/mystore?key=config1&key=config2
GET http://localhost:<daprPort>/v1.0/configuration/mystore?key=config1&key=config2
```
To retrieve all configuration items:
```
GET http://localhost:<daprPort>/v1.0-alpha1/configuration/mystore
GET http://localhost:<daprPort>/v1.0/configuration/mystore
```
#### Request Body
@ -59,7 +59,7 @@ JSON-encoded value of key/value pairs for each configuration item.
### Example
```shell
curl -X GET 'http://localhost:3500/v1.0-alpha1/configuration/mystore?key=myConfigKey'
curl -X GET 'http://localhost:3500/v1.0/configuration/mystore?key=myConfigKey'
```
> The above command returns the following JSON:
@ -75,7 +75,7 @@ This endpoint lets you subscribe to configuration changes. Notifications happen
### HTTP Request
```
GET http://localhost:<daprPort>/v1.0-alpha1/configuration/<storename>/subscribe
GET http://localhost:<daprPort>/v1.0/configuration/<storename>/subscribe
```
#### URL Parameters
@ -91,13 +91,13 @@ If no query parameters are provided, all configuration items are subscribed to.
To specify the keys of the configuration items to subscribe to, use one or more `key` query parameters. For example:
```
GET http://localhost:<daprPort>/v1.0-alpha1/configuration/mystore/subscribe?key=config1&key=config2
GET http://localhost:<daprPort>/v1.0/configuration/mystore/subscribe?key=config1&key=config2
```
To subscribe to all changes:
```
GET http://localhost:<daprPort>/v1.0-alpha1/configuration/mystore/subscribe
GET http://localhost:<daprPort>/v1.0/configuration/mystore/subscribe
```
#### Request Body
@ -121,7 +121,7 @@ JSON-encoded value
### Example
```shell
curl -X GET 'http://localhost:3500/v1.0-alpha1/configuration/mystore/subscribe?key=myConfigKey'
curl -X GET 'http://localhost:3500/v1.0/configuration/mystore/subscribe?key=myConfigKey'
```
> The above command returns the following JSON:
@ -141,7 +141,7 @@ This endpoint lets you unsubscribe to configuration changes.
### HTTP Request
```
GET http://localhost:<daprPort>/v1.0-alpha1/configuration/<storename>/<subscription-id>/unsubscribe
GET http://localhost:<daprPort>/v1.0/configuration/<storename>/<subscription-id>/unsubscribe
```
#### URL Parameters
@ -181,7 +181,7 @@ Code | Description
### Example
```shell
curl -X GET 'http://localhost:3500/v1.0-alpha1/configuration/mystore/bf3aa454-312d-403c-af95-6dec65058fa2/unsubscribe'
curl -X GET 'http://localhost:3500/v1.0/configuration/mystore/bf3aa454-312d-403c-af95-6dec65058fa2/unsubscribe'
```
## Optional application (user code) routes

View File

@ -23,7 +23,7 @@ This table is meant to help users understand the equivalent options for running
| `--dapr-http-port` | `--dapr-http-port` | | not supported | The HTTP port for the Dapr API |
| `--dapr-http-max-request-size` | --dapr-http-max-request-size | | `dapr.io/http-max-request-size` | Increasing max size of request body http and grpc servers parameter in MB to handle uploading of big files. Default is `4` MB |
| `--dapr-http-read-buffer-size` | --dapr-http-read-buffer-size | | `dapr.io/http-read-buffer-size` | Increasing max size of http header read buffer in KB to handle when sending multi-KB headers. The default 4 KB. When sending bigger than default 4KB http headers, you should set this to a larger value, for example 16 (for 16KB) |
| not supported | `--image` | | `dapr.io/sidecar-image` | Dapr sidecar image. Default is `daprio/daprd:latest`. Use this when building your own custom image of Dapr and the Dapr sidecar will use this image instead of the default image of Dapr |
| not supported | `--image` | | `dapr.io/sidecar-image` | Dapr sidecar image. Default is daprio/daprd:latest. The Dapr sidecar uses this image instead of the latest default image. Use this when building your own custom image of Dapr and or [using an alternative stable Dapr image]({{<ref "support-release-policy.md#build-variations" >}}) |
| `--internal-grpc-port` | not supported | | not supported | gRPC port for the Dapr Internal API to listen on |
| `--enable-metrics` | not supported | | configuration spec | Enable prometheus metric (default true) |
| `--enable-mtls` | not supported | | configuration spec | Enables automatic mTLS for daprd to daprd communication channels |

View File

@ -28,6 +28,7 @@ dapr run [flags] [command]
| `--app-port`, `-p` | `APP_PORT` | | The port your application is listening on |
| `--app-protocol`, `-P` | | `http` | The protocol Dapr uses to talk to the application. Valid values are: `http`, `grpc`, `https` (HTTP with TLS), `grpcs` (gRPC with TLS), `h2c` (HTTP/2 Cleartext) |
| `--resources-path`, `-d` | | Linux/Mac: `$HOME/.dapr/components` <br/>Windows: `%USERPROFILE%\.dapr\components` | The path for components directory |
| `--app-channel-address` | | `127.0.0.1` | The network address the application listens on |
| `--runtime-path` | | | Dapr runtime install path |
| `--config`, `-c` | | Linux/Mac: `$HOME/.dapr/config.yaml` <br/>Windows: `%USERPROFILE%\.dapr\config.yaml` | Dapr configuration file |
| `--dapr-grpc-port`, `-G` | `DAPR_GRPC_PORT` | `50001` | The gRPC port for Dapr to listen on |

View File

@ -25,11 +25,11 @@ spec:
- name: url
value: http://something.com
- name: MTLSRootCA
value: /Users/somepath/root.pem # OPTIONAL <path to root CA> or <pem encoded string>
value: /Users/somepath/root.pem # OPTIONAL Secret store ref, <path to root CA>, or <pem encoded string>
- name: MTLSClientCert
value: /Users/somepath/client.pem # OPTIONAL <path to client cert> or <pem encoded string>
value: /Users/somepath/client.pem # OPTIONAL Secret store ref, <path to client cert>, or <pem encoded string>
- name: MTLSClientKey
value: /Users/somepath/client.key # OPTIONAL <path to client key> or <pem encoded string>
value: /Users/somepath/client.key # OPTIONAL Secret store ref, <path to client key>, or <pem encoded string>
- name: MTLSRenegotiation
value: RenegotiateOnceAsClient # OPTIONAL one of: RenegotiateNever, RenegotiateOnceAsClient, RenegotiateFreelyAsClient
- name: securityToken # OPTIONAL <token to include as a header on HTTP requests>
@ -45,13 +45,43 @@ spec:
| Field | Required | Binding support | Details | Example |
|--------------------|:--------:|--------|--------|---------|
| url | Y | Output |The base URL of the HTTP endpoint to invoke | `http://host:port/path`, `http://myservice:8000/customers`
| MTLSRootCA | N | Output |Path to root ca certificate or pem encoded string |
| MTLSClientCert | N | Output |Path to client certificate or pem encoded string |
| MTLSClientKey | N | Output |Path client private key or pem encoded string |
| MTLSRootCA | N | Output |Secret store reference, path to root ca certificate, or pem encoded string |
| MTLSClientCert | N | Output |Secret store reference, path to client certificate, or pem encoded string |
| MTLSClientKey | N | Output |Secret store reference, path client private key, or pem encoded string |
| MTLSRenegotiation | N | Output |Type of TLS renegotiation to be used | `RenegotiateOnceAsClient`
| securityToken | N | Output |The value of a token to be added to an HTTP request as a header. Used together with `securityTokenHeader` |
| securityTokenHeader| N | Output |The name of the header for `securityToken` on an HTTP request that |
### How to configure MTLS related fields in Metadata
The values for **MTLSRootCA**, **MTLSClientCert** and **MTLSClientKey** can be provided in three ways:
1. Secret store reference
```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: <NAME>
spec:
type: bindings.http
version: v1
metadata:
- name: url
value: http://something.com
- name: MTLSRootCA
secretKeyRef:
name: mysecret
key: myrootca
auth:
secretStore: <NAME_OF_SECRET_STORE_COMPONENT>
```
2. Path to the file: The absolute path to the file can be provided as a value for the field.
3. PEM encoded string: The PEM encoded string can also be provided as a value for the field.
{{% alert title="Note" color="primary" %}}
Metadata fields **MTLSRootCA**, **MTLSClientCert** and **MTLSClientKey** are used to configure TLS(m) authentication.
To use mTLS authentication, you must provide all three fields. See [mTLS]({{< ref "#using-mtls-or-enabling-client-tls-authentication-along-with-https" >}}) for more details. You can also provide only **MTLSRootCA**, to enable **HTTPS** connection. See [HTTPS]({{< ref "#install-the-ssl-certificate-in-the-sidecar" >}}) section for more details.
{{% /alert %}}
## Binding support
This component supports **output binding** with the following [HTTP methods/verbs](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html):
@ -316,6 +346,10 @@ curl -d '{ "operation": "get" }' \
{{< /tabs >}}
{{% alert title="Note" color="primary" %}}
HTTPS binding support can also be configured using the **MTLSRootCA** metadata option. This will add the specified certificate to the list of trusted certificates for the binding. There's no specific preference for either method. While the **MTLSRootCA** option is easy to use and doesn't require any changes to the sidecar, it accepts only one certificate. If you need to trust multiple certificates, you need to [install them in the sidecar by following the steps above]({{< ref "#install-the-ssl-certificate-in-the-sidecar" >}}).
{{% /alert %}}
## Using mTLS or enabling client TLS authentication along with HTTPS
You can configure the HTTP binding to use mTLS or client TLS authentication along with HTTPS by providing the `MTLSRootCA`, `MTLSClientCert`, and `MTLSClientKey` metadata fields in the binding component.

View File

@ -1,7 +1,7 @@
---
type: docs
title: "MySQL binding spec"
linkTitle: "MySQL"
title: "MySQL & MariaDB binding spec"
linkTitle: "MySQL & MariaDB"
description: "Detailed documentation on the MySQL binding component"
aliases:
- "/operations/components/setup-bindings/supported-bindings/mysql/"
@ -9,7 +9,9 @@ aliases:
## Component format
To setup MySQL binding create a component of type `bindings.mysql`. See [this guide]({{< ref "howto-bindings.md#1-create-a-binding" >}}) on how to create and apply a binding configuration.
The MySQL binding allows connecting to both MySQL and MariaDB databases. In this document, we refer to "MySQL" to indicate both databases.
To setup a MySQL binding create a component of type `bindings.mysql`. See [this guide]({{< ref "howto-bindings.md#1-create-a-binding" >}}) on how to create and apply a binding configuration.
The MySQL binding uses [Go-MySQL-Driver](https://github.com/go-sql-driver/mysql) internally.

View File

@ -100,7 +100,7 @@ The Azure App Configuration store component supports the following optional `lab
The label can be populated using query parameters in the request URL:
```bash
GET curl http://localhost:<daprPort>/v1.0-alpha1/configuration/<store-name>?key=<key name>&metadata.label=<label value>
GET curl http://localhost:<daprPort>/v1.0/configuration/<store-name>?key=<key name>&metadata.label=<label value>
```
## Related links

View File

@ -39,7 +39,7 @@ The above example uses secrets as plain strings. It is recommended to use a secr
| Field | Required | Details | Example |
|--------------------|:--------:|---------|---------|
| connectionString | Y | The connection string for PostgreSQL. Default pool_max_conns = 5 | `"host=localhost user=postgres password=example port=5432 connect_timeout=10 database=dapr_test pool_max_conns=10"`
| table | Y | table name for configuration information. | `configTable`
| table | Y | Table name for configuration information, must be lowercased. | `configtable`
## Set up PostgreSQL as Configuration Store
@ -96,7 +96,7 @@ notification = json_build_object(
6. Since this is a generic created trigger, map this trigger to `configuration table`
```console
CREATE TRIGGER config
AFTER INSERT OR UPDATE OR DELETE ON configTable
AFTER INSERT OR UPDATE OR DELETE ON configtable
FOR EACH ROW EXECUTE PROCEDURE notify_event();
```
7. In the subscribe request add an additional metadata field with key as `pgNotifyChannel` and value should be set to same `channel name` mentioned in `pg_notify`. From the above example, it should be set to `config`

View File

@ -20,19 +20,11 @@ spec:
version: v1
metadata:
- name: redisHost
value: <HOST>
value: <address>:6379
- name: redisPassword
value: <PASSWORD>
value: **************
- name: enableTLS
value: <bool> # Optional. Allowed: true, false.
- name: failover
value: <bool> # Optional. Allowed: true, false.
- name: sentinelMasterName
value: <string> # Optional
- name: maxRetries
value: # Optional
- name: maxRetryBackoff
value: # Optional
value: <bool>
```
@ -45,14 +37,26 @@ The above example uses secrets as plain strings. It is recommended to use a secr
| Field | Required | Details | Example |
|--------------------|:--------:|---------|---------|
| redisHost | Y | Connection-string for the redis host | `localhost:6379`, `redis-master.default.svc.cluster.local:6379`
| redisPassword | Y | Password for Redis host. No Default. Can be `secretKeyRef` to use a secret reference | `""`, `"KeFg23!"`
| enableTLS | N | If the Redis instance supports TLS with public certificates, can be configured to be enabled or disabled. Defaults to `"false"` | `"true"`, `"false"`
| maxRetries | N | Maximum number of retries before giving up. Defaults to `3` | `5`, `10`
| maxRetryBackoff | N | Maximum backoff between each retry. Defaults to `2` seconds; `"-1"` disables backoff. | `3000000000`
| failover | N | Property to enabled failover configuration. Needs sentinalMasterName to be set. The redisHost should be the sentinel host address. See [Redis Sentinel Documentation](https://redis.io/docs/manual/sentinel/). Defaults to `"false"` | `"true"`, `"false"`
| sentinelMasterName | N | The sentinel master name. See [Redis Sentinel Documentation](https://redis.io/docs/manual/sentinel/) | `""`, `"127.0.0.1:6379"`
| redisHost | Y | Output | The Redis host address | `"localhost:6379"` |
| redisPassword | Y | Output | The Redis password | `"password"` |
| redisUsername | N | Output | Username for Redis host. Defaults to empty. Make sure your Redis server version is 6 or above, and have created acl rule correctly. | `"username"` |
| enableTLS | N | Output | If the Redis instance supports TLS with public certificates it can be configured to enable or disable TLS. Defaults to `"false"` | `"true"`, `"false"` |
| failover | N | Output | Property to enabled failover configuration. Needs sentinelMasterName to be set. Defaults to `"false"` | `"true"`, `"false"`
| sentinelMasterName | N | Output | The Sentinel master name. See [Redis Sentinel Documentation](https://redis.io/docs/reference/sentinel-clients/) | `""`, `"127.0.0.1:6379"`
| redisType | N | Output | The type of Redis. There are two valid values, one is `"node"` for single node mode, the other is `"cluster"` for Redis cluster mode. Defaults to `"node"`. | `"cluster"`
| redisDB | N | Output | Database selected after connecting to Redis. If `"redisType"` is `"cluster"`, this option is ignored. Defaults to `"0"`. | `"0"`
| redisMaxRetries | N | Output | Maximum number of times to retry commands before giving up. Default is to not retry failed commands. | `"5"`
| redisMinRetryInterval | N | Output | Minimum backoff for Redis commands between each retry. Default is `"8ms"`; `"-1"` disables backoff. | `"8ms"`
| redisMaxRetryInterval | N | Output | Maximum backoff for Redis commands between each retry. Default is `"512ms"`;`"-1"` disables backoff. | `"5s"`
| dialTimeout | N | Output | Dial timeout for establishing new connections. Defaults to `"5s"`. | `"5s"`
| readTimeout | N | Output | Timeout for socket reads. If reached, Redis commands fail with a timeout instead of blocking. Defaults to `"3s"`, `"-1"` for no timeout. | `"3s"`
| writeTimeout | N | Output | Timeout for socket writes. If reached, Redis commands fail with a timeout instead of blocking. Defaults is readTimeout. | `"3s"`
| poolSize | N | Output | Maximum number of socket connections. Default is 10 connections per every CPU as reported by runtime.NumCPU. | `"20"`
| poolTimeout | N | Output | Amount of time client waits for a connection if all connections are busy before returning an error. Default is readTimeout + 1 second. | `"5s"`
| maxConnAge | N | Output | Connection age at which the client retires (closes) the connection. Default is to not close aged connections. | `"30m"`
| minIdleConns | N | Output | Minimum number of idle connections to keep open in order to avoid the performance degradation associated with creating new connections. Defaults to `"0"`. | `"2"`
| idleCheckFrequency | N | Output | Frequency of idle checks made by idle connections reaper. Default is `"1m"`. `"-1"` disables idle connections reaper. | `"-1"`
| idleTimeout | N | Output | Amount of time after which the client closes idle connections. Should be less than server's timeout. Default is `"5m"`. `"-1"` disables idle timeout check. | `"10m"`
## Setup Redis

View File

@ -7,12 +7,13 @@ description: Detailed information on the JWKS cryptography component
## Component format
The purpose of this component is to load keys from a JSON Web Key Set (RFC-7517). These are JSON documents that contain 1 or more keys as JWK (JSON Web Key); they can be public, private, or shared keys.
The purpose of this component is to load keys from a JSON Web Key Set ([RFC 7517](https://www.rfc-editor.org/rfc/rfc7517)). These are JSON documents that contain 1 or more keys as JWK (JSON Web Key); they can be public, private, or shared keys.
This component supports loading a JWKS:
- From a local file (if the file is changed on disk, it's reloaded automatically),
- From a HTTP(S) URL (periodically refreshed if needed), or
- By passing an actual JWKS in the Component YAML (as a string, which can be base64-encoded).
- From a local file; in this case, Dapr watches for changes to the file on disk and reloads it automatically.
- From a HTTP(S) URL, which is periodically refreshed.
- By passing the actual JWKS in the `jwks` metadata property, as a string (optionally, base64-encoded).
{{% alert title="Note" color="primary" %}}
This component uses the cryptographic engine in Dapr to perform operations. Although keys are never exposed to your application, Dapr has access to the raw key material.
@ -27,11 +28,39 @@ kind: Component
metadata:
name: jwks
spec:
type: crypto.jwks
type: crypto.dapr.jwks
version: v1
metadata:
- name: jwks
value: fixtures/crypto/jwks/jwks.json
# Example 1: load JWKS from file
- name: "jwks"
value: "fixtures/crypto/jwks/jwks.json"
# Example 2: load JWKS from a HTTP(S) URL
# Only "jwks" is required
- name: "jwks"
value: "https://example.com/.well-known/jwks.json"
- name: "requestTimeout"
value: "30s"
- name: "minRefreshInterval"
value: "10m"
# Option 3: include the actual JWKS
- name: "jwks"
value: |
{
"keys": [
{
"kty": "RSA",
"use": "sig",
"kid": "…",
"n": "…",
"e": "…",
"issuer": "https://example.com"
}
]
}
# Option 3b: include the JWKS base64-encoded
- name: "jwks"
value: |
eyJrZXlzIjpbeyJ…
```
{{% alert title="Warning" color="warning" %}}
@ -42,9 +71,9 @@ The above example uses secrets as plain strings. It is recommended to use a secr
| Field | Required | Details | Example |
|--------------------|:--------:|---------|---------|
| jwks | Y | Connection-string for the JWKS host | `fixtures/crypto/jwks/jwks.json`
| requestTimeout | N | Amount of time before request timeout; Default: 30 seconds | `30`
| minRefreshInterval | N | Minimum interval for request refresh; Default: 10 minutes | `10`
| `jwks` | Y | Path to the JWKS document | Local file: `"fixtures/crypto/jwks/jwks.json"`<br>HTTP(S) URL: `"https://example.com/.well-known/jwks.json"`<br>Embedded JWKS: `{"keys": […]}` (can be base64-encoded)
| `requestTimeout` | N | Timeout for network requests when fetching the JWKS document from a HTTP(S) URL, as a Go duration. Default: "30s" | `"5s"`
| `minRefreshInterval` | N | Minimum interval to wait before subsequent refreshes of the JWKS document from a HTTP(S) source, as a Go duration. Default: "10m" | `"1h"`
## Related links
[Cryptography building block]({{< ref cryptography >}})

View File

@ -22,7 +22,7 @@ kind: Component
metadata:
name: <NAME>
spec:
type: crypto.<TYPE>
type: crypto.dapr.kubernetes.secrets
version: v1
metadata:
- name: defaultNamespace

View File

@ -7,7 +7,15 @@ description: Detailed information on the local storage cryptography component
## Component format
The purpose of this component is to load keys from a local directory. The component accepts as input the name of a folder, and loads keys from there. Each key is in its own file, and when users request a key with a given name, Dapr will load the file with that name.
The purpose of this component is to load keys from a local directory.
The component accepts as input the name of a folder, and loads keys from there. Each key is in its own file, and when users request a key with a given name, Dapr loads the file with that name.
Supported file formats:
- PEM with public and private keys (supports: PKCS#1, PKCS#8, PKIX)
- JSON Web Key (JWK) containing public, private, or symmetric keys
- Raw key data for symmetric keys
{{% alert title="Note" color="primary" %}}
This component uses the cryptographic engine in Dapr to perform operations. Although keys are never exposed to your application, Dapr has access to the raw key material.
@ -23,7 +31,7 @@ kind: Component
metadata:
name: mycrypto
spec:
type: crypto.localstorage
type: crypto.dapr.localstorage
metadata:
version: v1
- name: path

View File

@ -28,6 +28,8 @@ spec:
value: "public"
- name: token
value: "eyJrZXlJZCI6InB1bHNhci1wajU0cXd3ZHB6NGIiLCJhbGciOiJIUzI1NiJ9.eyJzd"
- name: consumerID
value: "topic1"
- name: namespace
value: "default"
- name: persistent
@ -66,6 +68,7 @@ spec:
| enableTLS | N | Enable TLS. Default: `"false"` | `"true"`, `"false"` |
| token | N | Enable Authentication. | [How to create pulsar token](https://pulsar.apache.org/docs/en/security-jwt/#generate-tokens)|
| tenant | N | The topic tenant within the instance. Tenants are essential to multi-tenancy in Pulsar, and spread across clusters. Default: `"public"` | `"public"` |
| consumerID | N | Used to set the subscription name or consumer ID. | `"topic1"`
| namespace | N | The administrative unit of the topic, which acts as a grouping mechanism for related topics. Default: `"default"` | `"default"`
| persistent | N | Pulsar supports two kinds of topics: [persistent](https://pulsar.apache.org/docs/en/concepts-architecture-overview#persistent-storage) and [non-persistent](https://pulsar.apache.org/docs/en/concepts-messaging/#non-persistent-topics). With persistent topics, all messages are durably persisted on disks (if the broker is not standalone, messages are durably persisted on multiple disks), whereas data for non-persistent topics is not persisted to storage disks.
| disableBatching | N | disable batching.When batching enabled default batch delay is set to 10 ms and default batch size is 1000 messages,Setting `disableBatching: true` will make the producer to send messages individually. Default: `"false"` | `"true"`, `"false"`|

View File

@ -70,6 +70,10 @@ In order to setup Cosmos DB as a state store, you need the following properties
- **Database**: The name of the database
- **Collection**: The name of the collection (or container)
### TTLs and cleanups
This state store supports [Time-To-Live (TTL)]({{< ref state-store-ttl.md >}}) for records stored with Dapr. When storing data using Dapr, you can set the `ttlInSeconds` metadata property to override the default TTL on the CosmodDB container, indicating when the data should be considered "expired". Note that this value _only_ takes effect if the container's `DefaultTimeToLive` field has a non-NULL value. See the [CosmosDB documentation](https://docs.microsoft.com/azure/cosmos-db/nosql/time-to-live) for more information.
## Best Practices for Production Use
Azure Cosmos DB shares a strict metadata request rate limit across all databases in a single Azure Cosmos DB account. New connections to Azure Cosmos DB assume a large percentage of the allowable request rate limit. (See the [Cosmos DB documentation](https://docs.microsoft.com/azure/cosmos-db/sql/troubleshoot-request-rate-too-large#recommended-solution-3))

View File

@ -1,7 +1,7 @@
---
type: docs
title: "MySQL"
linkTitle: "MySQL"
title: "MySQL & MariaDB"
linkTitle: "MySQL & MariaDB"
description: Detailed information on the MySQL state store component
aliases:
- "/operations/components/setup-state-store/supported-state-stores/setup-mysql/"
@ -9,6 +9,8 @@ aliases:
## Component format
The MySQL state store components allows connecting to both MySQL and MariaDB databases. In this document, we refer to "MySQL" to indicate both databases.
To setup MySQL state store create a component of type `state.mysql`. See [this guide]({{< ref "howto-get-save-state.md#step-1-setup-a-state-store" >}}) on how to create and apply a state store configuration.
@ -56,6 +58,7 @@ If you wish to use MySQL as an actor store, append the following to the yaml.
| `timeoutInSeconds` | N | Timeout for all database operations. Defaults to `20` | `30` |
| `pemPath` | N | Full path to the PEM file to use for [enforced SSL Connection](#enforced-ssl-connection) required if pemContents is not provided. Cannot be used in K8s environment | `"/path/to/file.pem"`, `"C:\path\to\file.pem"` |
| `pemContents` | N | Contents of PEM file to use for [enforced SSL Connection](#enforced-ssl-connection) required if pemPath is not provided. Can be used in K8s environment | `"pem value"` |
| `cleanupIntervalInSeconds` | N | Interval, in seconds, to clean up rows with an expired TTL. Default: `3600` (that is 1 hour). Setting this to values <=0 disables the periodic cleanup. | `1800`, `-1`
## Setup MySQL
@ -132,6 +135,17 @@ Replace the `<CONNECTION STRING>` value with your connection string. The connect
If your server requires SSL your connection string must end with `&tls=custom` for example, `"<user>:<password>@tcp(<server>:3306)/?allowNativePasswords=true&tls=custom"`. You must replace the `<PEM PATH>` with a full path to the PEM file. The connection to MySQL will require a minimum TLS version of 1.2.
### TTLs and cleanups
This state store supports [Time-To-Live (TTL)]({{< ref state-store-ttl.md >}}) for records stored with Dapr. When storing data using Dapr, you can set the `ttlInSeconds` metadata property to indicate when the data should be considered "expired".
Because MySQL doesn't have built-in support for TTLs, this is implemented in Dapr by adding a column in the state table indicating when the data is to be considered "expired". Records that are "expired" are not returned to the caller, even if they're still physically stored in the database. A background "garbage collector" periodically scans the state table for expired rows and deletes them.
The interval at which the deletion of expired records happens is set with the `cleanupIntervalInSeconds` metadata property, which defaults to 3600 seconds (that is, 1 hour).
- Longer intervals require less frequent scans for expired rows, but can require storing expired records for longer, potentially requiring more storage space. If you plan to store many records in your state table, with short TTLs, consider setting `cleanupIntervalInSeconds` to a smaller value, for example `300` (300 seconds, or 5 minutes).
- If you do not plan to use TTLs with Dapr and the MySQL state store, you should consider setting `cleanupIntervalInSeconds` to a value <= 0 (e.g. `0` or `-1`) to disable the periodic cleanup and reduce the load on the database.
## Related links
- [Basic schema for a Dapr component]({{< ref component-schema >}})
- Read [this guide]({{< ref "howto-get-save-state.md#step-2-save-and-retrieve-a-single-state" >}}) for instructions on configuring state store components

View File

@ -92,7 +92,7 @@ Either the default "postgres" database can be used, or create a new database for
### TTLs and cleanups
This state store supports [Time-To-Live (TTL)](https://docs.dapr.io/developing-applications/building-blocks/state-management/state-store-ttl/) for records stored with Dapr. When storing data using Dapr, you can set the `ttlInSeconds` metadata property to indicate after how many seconds the data should be considered "expired".
This state store supports [Time-To-Live (TTL)]({{< ref state-store-ttl.md >}}) for records stored with Dapr. When storing data using Dapr, you can set the `ttlInSeconds` metadata property to indicate after how many seconds the data should be considered "expired".
Because PostgreSQL doesn't have built-in support for TTLs, this is implemented in Dapr by adding a column in the state table indicating when the data is to be considered "expired". Records that are "expired" are not returned to the caller, even if they're still physically stored in the database. A background "garbage collector" periodically scans the state table for expired rows and deletes them.

View File

@ -10,13 +10,11 @@ The following table lists the environment variables used by the Dapr runtime, CL
| Environment Variable | Used By | Description |
| -------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| APP_ID | Your application | The id for your application, used for service discovery |
| APP_PORT | Your application | The port your application is listening on |
| APP_ID | Your application | The id for your application, used for service discovery |
| APP_PORT | Dapr sidecar | The port your application is listening on |
| APP_API_TOKEN | Your application | The token used by the application to authenticate requests from Dapr API. Read [authenticate requests from Dapr using token authentication]({{< ref app-api-token >}}) for more information. |
| DAPR_HTTP_PORT | Your application | The HTTP port that the Dapr sidecar is listening on. Your application should use this variable to connect to Dapr sidecar instead of hardcoding the port value. Set by the Dapr CLI run command for self-hosted or injected by the `dapr-sidecar-injector` into all the containers in the pod. |
| DAPR_GRPC_PORT | Your application | The gRPC port that the Dapr sidecar is listening on. Your application should use this variable to connect to Dapr sidecar instead of hardcoding the port value. Set by the Dapr CLI run command for self-hosted or injected by the `dapr-sidecar-injector` into all the containers in the pod. |
| DAPR_METRICS_PORT | Your application | The HTTP [Prometheus]({{< ref prometheus >}}) port to which Dapr sends its metrics information. With this variable, your application sends its application-specific metrics to have both Dapr metrics and application metrics together. See [metrics-port]({{< ref arguments-annotations-overview>}}) for more information |
| DAPR_PROFILE_PORT | Your application | The [profiling port]({{< ref profiling-debugging >}}) through which Dapr lets you enable profiling and track possible CPU/memory/resource spikes in your application's behavior. Enabled by `--enable-profiling` command in Dapr CLI for self-hosted or `dapr.io/enable-profiling` annotation in Dapr annotated pod. |
| DAPR_API_TOKEN | Dapr sidecar | The token used for Dapr API authentication for requests from the application. [Enable API token authentication in Dapr]({{< ref api-token >}}). |
| NAMESPACE | Dapr sidecar | Used to specify a component's [namespace in self-hosted mode]({{< ref component-scopes >}}). |
| DAPR_DEFAULT_IMAGE_REGISTRY | Dapr CLI | In self-hosted mode, it is used to specify the default container registry to pull images from. When its value is set to `GHCR` or `ghcr`, it pulls the required images from Github container registry. To default to Docker hub, unset this environment variable. |

View File

@ -62,7 +62,7 @@
features:
input: true
output: true
- component: MySQL
- component: MySQL & MariaDB
link: mysql
state: Alpha
version: v1

View File

@ -1 +1 @@
{{- if .Get "short" }}1.10{{ else if .Get "long" }}1.10.5{{ else if .Get "cli" }}1.10.0{{ else }}1.10.5{{ end -}}
{{- if .Get "short" }}1.10{{ else if .Get "long" }}1.10.7{{ else if .Get "cli" }}1.10.0{{ else }}1.10.7{{ end -}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 686 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB