Update configuration api (#3410)

* updating alpha1 endpoint to stable

Signed-off-by: Shivam Kumar <shivamkm07@gmail.com>

* lowercaing table name in postgres

Signed-off-by: Shivam Kumar <shivamkm07@gmail.com>

* updating redis metadata

Signed-off-by: Shivam Kumar <shivamkm07@gmail.com>

* updating redis and postgres to stable

Signed-off-by: Shivam Kumar <shivamkm07@gmail.com>

* updating configuration manage: wip

Signed-off-by: Shivam Kumar <shivamkm07@gmail.com>

* Apply suggestions from code review

Co-authored-by: Mark Fussell <markfussell@gmail.com>
Co-authored-by: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com>
Signed-off-by: Shivam Kumar <shivamkm07@gmail.com>

* adding demo link

Signed-off-by: Shivam Kumar <shivamkm07@gmail.com>

* updating sdk codes

Signed-off-by: Shivam Kumar <shivamkm07@gmail.com>

* adding java sdk subscribe

Signed-off-by: Shivam Kumar <shivamkm07@gmail.com>

* adding javascript sdk subscribe

Signed-off-by: Shivam Kumar <shivamkm07@gmail.com>

* adding sdk unsubscribe

Signed-off-by: Shivam Kumar <shivamkm07@gmail.com>

* adding quotes

Signed-off-by: Shivam Kumar <shivamkm07@gmail.com>

* Update howto-manage-configuration.md

Updating a small grammar change

---------

Signed-off-by: Shivam Kumar <shivamkm07@gmail.com>
Co-authored-by: Mark Fussell <markfussell@gmail.com>
Co-authored-by: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com>
This commit is contained in:
Shivam Kumar 2023-05-29 21:55:19 +05:30 committed by GitHub
parent 46f9f4d06d
commit 5696e3ccdf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 527 additions and 169 deletions

View File

@ -27,6 +27,6 @@ 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.

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

@ -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,502 @@ 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 = ""
```bash
dapr run --app-id orderprocessing --resources-path components/ -- python3 OrderProcessingService.py
with DaprClient() as d:
isSuccess = d.unsubscribe_configuration(store_name='configstore', id=subscriptionID)
print(f"Unsubscribed successfully? {isSuccess}", flush=True)
```
{{% /codetab %}}
{{< /tabs >}}
{{% codetab %}}
```go
package main
#### Stop watching configuration items
import (
"context"
"encoding/json"
"fmt"
"log"
"os"
"time"
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:
dapr "github.com/dapr/go-sdk/client"
)
```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;
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 %}}
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.
{{% 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
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 %}}
## Next steps
* Read [configuration API overview]({{< ref configuration-api-overview.md >}})
* Read [configuration API overview]({{< ref configuration-api-overview.md >}})

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

@ -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