From 36743211b034b7eb2f352235b09f217025f39e6f Mon Sep 17 00:00:00 2001 From: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> Date: Wed, 4 Jan 2023 17:10:43 -0600 Subject: [PATCH] Configuration API quickstart docs (#3009) * new configuration api quickstart Signed-off-by: Hannah Hunter * add new file Signed-off-by: Hannah Hunter * updates per sarthak Signed-off-by: Hannah Hunter * add diagram Signed-off-by: Hannah Hunter * updates per Mark Signed-off-by: Hannah Hunter Signed-off-by: Hannah Hunter --- .../configuration-api-overview.md | 33 +- .../howto-manage-configuration.md | 9 +- .../en/getting-started/quickstarts/_index.md | 1 + .../quickstarts/configuration-quickstart.md | 639 ++++++++++++++++++ .../configuration-quickstart-flow.png | Bin 0 -> 30297 bytes 5 files changed, 673 insertions(+), 9 deletions(-) create mode 100644 daprdocs/content/en/getting-started/quickstarts/configuration-quickstart.md create mode 100644 daprdocs/static/images/configuration-quickstart/configuration-quickstart-flow.png diff --git a/daprdocs/content/en/developing-applications/building-blocks/configuration/configuration-api-overview.md b/daprdocs/content/en/developing-applications/building-blocks/configuration/configuration-api-overview.md index 5f2ac9096..2e95f6b49 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/configuration/configuration-api-overview.md +++ b/daprdocs/content/en/developing-applications/building-blocks/configuration/configuration-api-overview.md @@ -6,17 +6,40 @@ weight: 1000 description: "Overview of the configuration API building block" --- -## Introduction +Consuming application configuration is a common task when writing applications. Frequently, configuration stores are used to manage this configuration data. A configuration item is often dynamic in nature and tightly coupled to the needs of the application that consumes it. -Consuming application configuration is a common task when writing applications and frequently configuration stores are used to manage this configuration data. A configuration item is often dynamic in nature and is tightly coupled to the needs of the application that consumes it. For example, common uses for application configuration include names of secrets, different identifiers, partition or consumer IDs, names of databases to connect to etc. These configuration items are typically stored as key/value items in a state store or database. Application configuration can be changed by either developers or operators at runtime and the developer needs to be notified of these changes in order to take the required action and load the new configuration. Also configuration data is typically read only from the application API perspective, with updates to the configuration store made through operator tooling. Dapr's configuration API allows developers to consume configuration items that are returned as read only key/value pairs and subscribe to changes whenever a configuration item changes. +For example, application configuration can include: +- Names of secrets +- Different identifiers +- Partition or consumer IDs +- Names of databases to connect to, etc + +Usually, configuration items are stored as key/value items in a state store or database. Developers or operators can change application configuration at runtime in the configuration store. Once changes are made, a service is notified to load the new configuration. + +Configuration data is read-only from the application API perspective, with updates to the configuration store made through operator tooling. With Dapr's configuration API, you can: +- Consume configuration items that are returned as read-only key/value pairs +- Subscribe to changes whenever a configuration item changes -It is worth noting that this configuration API should not be confused with the [Dapr sidecar and control plane configuration]({{}}) which is used to set policies and settings on instances of Dapr sidecars or the installed Dapr control plane. +{{% alert title="Note" color="primary" %}} + The Configuration API should not be confused with the [Dapr sidecar and control plane configuration]({{< ref "configuration-overview" >}}), which is used to set policies and settings on Dapr sidecar instances or the installed Dapr control plane. +{{% /alert %}} -*This API is currently in `Alpha` state* +## Try out configuration + +### Quickstart + +Want to put the Dapr configuration API to the test? Walk through the following quickstart to see the configuration API in action: + +| Quickstart | Description | +| ---------- | ----------- | +| [Configuration quickstart]({{< ref configuration-quickstart.md >}}) | Get configuration items or subscribe to configuration changes using the configuration API. | + +### Start using the configuration API directly in your app + +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 >}}). -## Features ## Next steps Follow these guides on: diff --git a/daprdocs/content/en/developing-applications/building-blocks/configuration/howto-manage-configuration.md b/daprdocs/content/en/developing-applications/building-blocks/configuration/howto-manage-configuration.md index 4de325ba6..b05722312 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/configuration/howto-manage-configuration.md +++ b/daprdocs/content/en/developing-applications/building-blocks/configuration/howto-manage-configuration.md @@ -8,12 +8,13 @@ description: "Learn how to get application configuration and subscribe for chang This example uses the Redis configuration store component to demonstrate how to retrieve a configuration item. +Diagram showing get configuration of example service + {{% alert title="Note" color="primary" %}} -This API is currently in `Alpha` state and only available on gRPC. An HTTP1.1 supported version with this URL syntax `/v1.0/configuration` will be available before the API is certified into `Stable` state. + If you haven't already, [try out the configuration quickstart]({{< ref configuration-quickstart.md >}}) for a quick walk-through on how to use the configuration API. {{% /alert %}} -Diagram showing get configuration of example service ## Create a configuration item in store @@ -68,7 +69,7 @@ spec: ## Retrieve Configuration Items ### Get configuration items using Dapr SDKs -{{< tabs Dotnet Java Python>}} +{{< tabs ".NET" Java Python>}} {{% codetab %}} @@ -304,7 +305,7 @@ asyncio.run(executeConfiguration()) ``` ```bash -dapr run --app-id orderprocessing --components-path components/ -- python3 OrderProcessingService.py +dapr run --app-id orderprocessing --resources-path components/ -- python3 OrderProcessingService.py ``` {{% /codetab %}} diff --git a/daprdocs/content/en/getting-started/quickstarts/_index.md b/daprdocs/content/en/getting-started/quickstarts/_index.md index 67380fa87..727b9a17b 100644 --- a/daprdocs/content/en/getting-started/quickstarts/_index.md +++ b/daprdocs/content/en/getting-started/quickstarts/_index.md @@ -27,4 +27,5 @@ Hit the ground running with our Dapr quickstarts, complete with code samples aim | [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. | | [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. | diff --git a/daprdocs/content/en/getting-started/quickstarts/configuration-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/configuration-quickstart.md new file mode 100644 index 000000000..bba89def1 --- /dev/null +++ b/daprdocs/content/en/getting-started/quickstarts/configuration-quickstart.md @@ -0,0 +1,639 @@ +--- +type: docs +title: "Quickstart: Configuration" +linkTitle: Configuration +weight: 76 +description: Get started with Dapr's Configuration building block +--- + +Let's take a look at Dapr's [Configuration building block]({{< ref configuration-api-overview.md >}}). A configuration item is often dynamic in nature and tightly coupled to the needs of the application that consumes it. Configuration items are key/value pairs containing configuration data, such as: +- App ids +- Partition keys +- Database names, etc + +In this quickstart, you'll run an `order-processor` microservice that utilizes the Configuration API. The service: +1. Gets configuration items from the configuration store. +1. Subscribes for configuration updates. + +Diagram that demonstrates the flow of the configuration API quickstart with key/value pairs used. + +Select your preferred language-specific Dapr SDK before proceeding with the Quickstart. + +{{< tabs "Python" "JavaScript" ".NET" "Java" "Go" >}} + +{{% codetab %}} + +### Pre-requisites + +For this example, you will need: + +- [Dapr CLI and initialized environment](https://docs.dapr.io/getting-started). +- [Python 3.7+ installed](https://www.python.org/downloads/). + +- [Docker Desktop](https://www.docker.com/products/docker-desktop) + + +### Step 1: Set up the environment + +Clone the [sample provided in the Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/configuration). + +```bash +git clone https://github.com/dapr/quickstarts.git +``` + +Once cloned, open a new terminal and run the following command to set values for configuration items `orderId1` and `orderId2`. + +```bash +docker exec dapr_redis redis-cli MSET orderId1 "101" orderId2 "102" +``` + +### Step 2: Run the `order-processor` service + +From the root of the Quickstarts clone directory, navigate to the `order-processor` directory. + +```bash +cd ./configuration/python/sdk/order-processor +``` + +Install the dependencies: + +```bash +pip3 install -r requirements.txt +``` + +Run the `order-processor` service alongside a Dapr sidecar. + +```bash +dapr run --app-id order-processor --resources-path ../../../components/ --app-port 6001 -- python3 app.py +``` + +> **Note**: Since Python3.exe is not defined in Windows, you may need to use `python app.py` instead of `python3 app.py`. + +The expected output: + +``` +== APP == Configuration for orderId1 : value: "101" +== APP == +== APP == Configuration for orderId2 : value: "102" +== APP == +== APP == App unsubscribed from config changes +``` + +### (Optional) Step 3: Update configuration item values + +Once the app has unsubscribed, try updating the configuration item values. Change the `orderId1` and `orderId2` values using the following command: + +```bash +docker exec dapr_redis redis-cli MSET orderId1 "103" orderId2 "104" +``` + +Run the `order-processor` service again: + +```bash +dapr run --app-id order-processor --resources-path ../../../components/ --app-port 6001 -- python3 app.py +``` + +> **Note**: Since Python3.exe is not defined in Windows, you may need to use `python app.py` instead of `python3 app.py`. + +The app will return the updated configuration values: + +``` +== APP == Configuration for orderId1 : value: "103" +== APP == +== APP == Configuration for orderId2 : value: "104" +== APP == +``` + +### The `order-processor` service + +The `order-processor` service includes code for: +- Getting the configuration items from the config store +- Subscribing to configuration updates (which you made in the CLI earlier) +- Unsubscribing from configuration updates and exiting the app after 20 seconds of inactivity. + +Get configuration items: + +```python +# Get config items from the config store +for config_item in CONFIGURATION_ITEMS: + config = client.get_configuration(store_name=DAPR_CONFIGURATION_STORE, keys=[config_item], config_metadata={}) + print(f"Configuration for {config_item} : {config.items[config_item]}", flush=True) +``` + +Subscribe to configuration updates: + +```python +# Subscribe for configuration changes +configuration = await client.subscribe_configuration(DAPR_CONFIGURATION_STORE, CONFIGURATION_ITEMS) +``` + +Unsubscribe from configuration updates and exit the application: + +```python +# Unsubscribe from configuration updates +unsubscribed = True +for config_item in CONFIGURATION_ITEMS: + unsub_item = client.unsubscribe_configuration(DAPR_CONFIGURATION_STORE, config_item) + #... +if unsubscribed == True: + print("App unsubscribed from config changes", flush=True) +``` + + +{{% /codetab %}} + + + +{{% codetab %}} + +### Pre-requisites + +For this example, you will need: + +- [Dapr CLI and initialized environment](https://docs.dapr.io/getting-started). +- [Python 3.7+ installed](https://www.python.org/downloads/). + +- [Docker Desktop](https://www.docker.com/products/docker-desktop) + + +### Step 1: Set up the environment + +Clone the [sample provided in the Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/configuration). + +```bash +git clone https://github.com/dapr/quickstarts.git +``` + +Once cloned, open a new terminal and run the following command to set values for configuration items `orderId1` and `orderId2`. + +```bash +docker exec dapr_redis redis-cli MSET orderId1 "101" orderId2 "102" +``` + +### Step 2: Run the `order-processor` service + +From the root of the Quickstarts clone directory, navigate to the `order-processor` directory. + +```bash +cd ./configuration/javascript/sdk/order-processor +``` + +Install the dependencies: + +```bash +npm install +``` + +Run the `order-processor` service alongside a Dapr sidecar. + +```bash +dapr run --app-id order-processor --resources-path ../../../components/ --app-protocol grpc --dapr-grpc-port 3500 -- node index.js +``` + +The expected output: + +``` +== APP == Configuration for orderId1: {"key":"orderId1","value":"101","version":"","metadata":{}} +== APP == Configuration for orderId2: {"key":"orderId2","value":"102","version":"","metadata":{}} +== APP == App unsubscribed to config changes +``` + +### (Optional) Step 3: Update configuration item values + +Once the app has unsubscribed, try updating the configuration item values. Change the `orderId1` and `orderId2` values using the following command: + +```bash +docker exec dapr_redis redis-cli MSET orderId1 "103" orderId2 "104" +``` + +Run the `order-processor` service again: + +```bash +dapr run --app-id order-processor --resources-path ../../../components/ --app-protocol grpc --dapr-grpc-port 3500 -- node index.js +``` + +The app will return the updated configuration values: + +``` +== APP == Configuration for orderId1: {"key":"orderId1","value":"103","version":"","metadata":{}} +== APP == Configuration for orderId2: {"key":"orderId2","value":"104","version":"","metadata":{}} +``` + +### The `order-processor` service + +The `order-processor` service includes code for: +- Getting the configuration items from the config store +- Subscribing to configuration updates (which you made in the CLI earlier) +- Unsubscribing from configuration updates and exiting the app after 20 seconds of inactivity. + +Get configuration items: + +```javascript +// Get config items from the config store +//... + 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])); + }); +``` + +Subscribe to configuration updates: + +```javascript +// 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 from configuration updates and exit the application: + +```javascript +// Unsubscribe to config updates and exit app after 20 seconds +setTimeout(() => { + stream.stop(); + console.log("App unsubscribed to config changes"); + process.exit(0); +}, +``` + +{{% /codetab %}} + + +{{% codetab %}} + +### 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). + +- [Docker Desktop](https://www.docker.com/products/docker-desktop) + + +### Step 1: Set up the environment + +Clone the [sample provided in the Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/configuration). + +```bash +git clone https://github.com/dapr/quickstarts.git +``` + +Once cloned, open a new terminal and run the following command to set values for configuration items `orderId1` and `orderId2`. + +```bash +docker exec dapr_redis redis-cli MSET orderId1 "101" orderId2 "102" +``` + +### Step 2: Run the `order-processor` service + +From the root of the Quickstarts clone directory, navigate to the `order-processor` directory. + +```bash +cd ./configuration/csharp/sdk/order-processor +``` + +Recall NuGet packages: + +```bash +dotnet restore +dotnet build +``` + +Run the `order-processor` service alongside a Dapr sidecar. + +```bash +dapr run --app-id order-processor-http --resources-path ../../../components/ --app-port 7001 -- dotnet run --project . +``` + +The expected output: + +``` +== APP == Configuration for orderId1: {"Value":"101","Version":"","Metadata":{}} +== APP == Configuration for orderId2: {"Value":"102","Version":"","Metadata":{}} +== APP == App unsubscribed from config changes +``` + +### (Optional) Step 3: Update configuration item values + +Once the app has unsubscribed, try updating the configuration item values. Change the `orderId1` and `orderId2` values using the following command: + +```bash +docker exec dapr_redis redis-cli MSET orderId1 "103" orderId2 "104" +``` + +Run the `order-processor` service again: + +```bash +dapr run --app-id order-processor-http --resources-path ../../../components/ --app-port 7001 -- dotnet run --project . +``` + +The app will return the updated configuration values: + +``` +== APP == Configuration for orderId1: {"Value":"103","Version":"","Metadata":{}} +== APP == Configuration for orderId2: {"Value":"104","Version":"","Metadata":{}} +``` + +### The `order-processor` service + +The `order-processor` service includes code for: +- Getting the configuration items from the config store +- Subscribing to configuration updates (which you made in the CLI earlier) +- Unsubscribing from configuration updates and exiting the app after 20 seconds of inactivity. + +Get configuration items: + +```csharp +// Get config from configuration store +GetConfigurationResponse config = await client.GetConfiguration(DAPR_CONFIGURATION_STORE, CONFIGURATION_ITEMS); +foreach (var item in config.Items) +{ + var cfg = System.Text.Json.JsonSerializer.Serialize(item.Value); + Console.WriteLine("Configuration for " + item.Key + ": " + cfg); +} +``` + +Subscribe to configuration updates: + +```csharp +// Subscribe to config updates +SubscribeConfigurationResponse subscribe = await client.SubscribeConfiguration(DAPR_CONFIGURATION_STORE, CONFIGURATION_ITEMS); +``` + +Unsubscribe from configuration updates and exit the application: + +```csharp +// Unsubscribe to config updates and exit the app +try +{ + client.UnsubscribeConfiguration(DAPR_CONFIGURATION_STORE, subscriptionId); + Console.WriteLine("App unsubscribed from config changes"); + Environment.Exit(0); +} +``` + +{{% /codetab %}} + + +{{% codetab %}} + +### Pre-requisites + +For this example, you will need: + +- [Dapr CLI and initialized environment](https://docs.dapr.io/getting-started). +- Java JDK 11 (or greater): + - [Oracle JDK](https://www.oracle.com/technetwork/java/javase/downloads/index.html#JDK11), or + - OpenJDK +- [Apache Maven](https://maven.apache.org/install.html), version 3.x. + +- [Docker Desktop](https://www.docker.com/products/docker-desktop) + + +### Step 1: Set up the environment + +Clone the [sample provided in the Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/configuration). + +```bash +git clone https://github.com/dapr/quickstarts.git +``` + +Once cloned, open a new terminal and run the following command to set values for configuration items `orderId1` and `orderId2`. + +```bash +docker exec dapr_redis redis-cli MSET orderId1 "101" orderId2 "102" +``` + +### Step 2: Run the `order-processor` service + +From the root of the Quickstarts clone directory, navigate to the `order-processor` directory. + +```bash +cd ./configuration/java/sdk/order-processor +``` + +Install the dependencies: + +```bash +mvn clean install +``` + +Run the `order-processor` service alongside a Dapr sidecar. + +```bash +dapr run --app-id order-processor --resources-path ../../../components -- java -jar target/OrderProcessingService-0.0.1-SNAPSHOT.jar +``` + +The expected output: + +``` +== APP == Configuration for orderId1: {'value':'101'} +== APP == Configuration for orderId2: {'value':'102'} +== APP == App unsubscribed to config changes +``` + +### (Optional) Step 3: Update configuration item values + +Once the app has unsubscribed, try updating the configuration item values. Change the `orderId1` and `orderId2` values using the following command: + +```bash +docker exec dapr_redis redis-cli MSET orderId1 "103" orderId2 "104" +``` + +Run the `order-processor` service again: + +```bash +dapr run --app-id order-processor --resources-path ../../../components -- java -jar target/OrderProcessingService-0.0.1-SNAPSHOT.jar +``` + +The app will return the updated configuration values: + +``` +== APP == Configuration for orderId1: {'value':'103'} +== APP == Configuration for orderId2: {'value':'104'} +``` + +### The `order-processor` service + +The `order-processor` service includes code for: +- Getting the configuration items from the config store +- Subscribing to configuration updates (which you made in the CLI earlier) +- Unsubscribing from configuration updates and exiting the app after 20 seconds of inactivity. + +Get configuration items: + +```java +// Get config items from the config store +try (DaprPreviewClient client = (new DaprClientBuilder()).buildPreviewClient()) { + for (String configurationItem : CONFIGURATION_ITEMS) { + ConfigurationItem item = client.getConfiguration(DAPR_CONFIGURATON_STORE, configurationItem).block(); + System.out.println("Configuration for " + configurationItem + ": {'value':'" + item.getValue() + "'}"); + } +``` + +Subscribe to configuration updates: + +```java +// Subscribe for config changes +Flux subscription = client.subscribeConfiguration(DAPR_CONFIGURATON_STORE, + CONFIGURATION_ITEMS.toArray(String[]::new)); +``` + +Unsubscribe from configuration updates and exit the application: + +```java +// Unsubscribe from config changes +UnsubscribeConfigurationResponse unsubscribe = client + .unsubscribeConfiguration(subscriptionId, DAPR_CONFIGURATON_STORE).block(); +if (unsubscribe.getIsUnsubscribed()) { + System.out.println("App unsubscribed to config changes"); +} +``` + +{{% /codetab %}} + + +{{% codetab %}} + +### Pre-requisites + +For this example, you will need: + +- [Dapr CLI and initialized environment](https://docs.dapr.io/getting-started). +- [Latest version of Go](https://go.dev/dl/). + +- [Docker Desktop](https://www.docker.com/products/docker-desktop) + + +### Step 1: Set up the environment + +Clone the [sample provided in the Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/configuration). + +```bash +git clone https://github.com/dapr/quickstarts.git +``` + +Once cloned, open a new terminal and run the following command to set values for configuration items `orderId1` and `orderId2`. + +```bash +docker exec dapr_redis redis-cli MSET orderId1 "101" orderId2 "102" +``` + +### Step 2: Run the `order-processor` service + +From the root of the Quickstarts clone directory, navigate to the `order-processor` directory. + +```bash +cd ./configuration/go/sdk/order-processor +``` + +Run the `order-processor` service alongside a Dapr sidecar. + +```bash +dapr run --app-id order-processor --app-port 6001 --resources-path ../../../components -- go run . +``` + +The expected output: + +``` +== APP == Configuration for orderId1: {"Value":"101","Version":"","Metadata":null} +== APP == Configuration for orderId2: {"Value":"102","Version":"","Metadata":null} +== APP == dapr configuration subscribe finished. +== APP == App unsubscribed to config changes +``` + +### (Optional) Step 3: Update configuration item values + +Once the app has unsubscribed, try updating the configuration item values. Change the `orderId1` and `orderId2` values using the following command: + +```bash +docker exec dapr_redis redis-cli MSET orderId1 "103" orderId2 "104" +``` + +Run the `order-processor` service again: + +```bash +dapr run --app-id order-processor --app-port 6001 --resources-path ../../../components -- go run . +``` + +The app will return the updated configuration values: + +``` +== APP == Configuration for orderId1: {"Value":"103","Version":"","Metadata":null} +== APP == Configuration for orderId2: {"Value":"104","Version":"","Metadata":null} +``` + +### The `order-processor` service + +The `order-processor` service includes code for: +- Getting the configuration items from the config store +- Subscribing to configuration updates (which you made in the CLI earlier) +- Unsubscribing from configuration updates and exiting the app after 20 seconds of inactivity. + +Get configuration items: + +```go +// Get config items from config store +for _, item := range CONFIGURATION_ITEMS { + config, err := client.GetConfigurationItem(ctx, DAPR_CONFIGURATION_STORE, item) + //... + c, _ := json.Marshal(config) + fmt.Println("Configuration for " + item + ": " + string(c)) +} +``` + +Subscribe to configuration updates: + +```go +// Subscribe for config changes +err = client.SubscribeConfigurationItems(ctx, DAPR_CONFIGURATION_STORE, CONFIGURATION_ITEMS, func(id string, config map[string]*dapr.ConfigurationItem) { + // First invocation when app subscribes to config changes only returns subscription id + if len(config) == 0 { + fmt.Println("App subscribed to config changes with subscription id: " + id) + subscriptionId = id + return + } +}) +``` + +Unsubscribe from configuration updates and exit the application: + +```go +// Unsubscribe to config updates and exit app after 20 seconds +select { +case <-ctx.Done(): + err = client.UnsubscribeConfigurationItems(context.Background(), DAPR_CONFIGURATION_STORE, subscriptionId) + //... + { + fmt.Println("App unsubscribed to config changes") + } +``` + +{{% /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 + +- Use Dapr Configuration with HTTP instead of an SDK. + - [Python](https://github.com/dapr/quickstarts/tree/master/configuration/python/http) + - [JavaScript](https://github.com/dapr/quickstarts/tree/master/configuration/javascript/http) + - [.NET](https://github.com/dapr/quickstarts/tree/master/configuration/csharp/http) + - [Java](https://github.com/dapr/quickstarts/tree/master/configuration/java/http) + - [Go](https://github.com/dapr/quickstarts/tree/master/configuration/go/http) +- Learn more about [Configuration building block]({{< ref configuration-api-overview >}}) + +{{< button text="Explore Dapr tutorials >>" page="getting-started/tutorials/_index.md" >}} \ No newline at end of file diff --git a/daprdocs/static/images/configuration-quickstart/configuration-quickstart-flow.png b/daprdocs/static/images/configuration-quickstart/configuration-quickstart-flow.png new file mode 100644 index 0000000000000000000000000000000000000000..29dc6f44c9e731845cb785981822f9bdd7265870 GIT binary patch literal 30297 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 BTF?Lh literal 0 HcmV?d00001