From b308ef5eaab31c3a716db07e3ac859bcdfa2e93f Mon Sep 17 00:00:00 2001 From: Nir Mashkowski Date: Fri, 27 May 2022 12:36:28 -0700 Subject: [PATCH 01/42] Binding quickstart - Cron input PostgreSQL output quickstart doc Signed-off-by: Nir Mashkowski --- .../en/getting-started/quickstarts/_index.md | 2 +- .../quickstarts/bindings-quickstart.md | 778 ++++++++++++++++++ 2 files changed, 779 insertions(+), 1 deletion(-) create mode 100644 daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md diff --git a/daprdocs/content/en/getting-started/quickstarts/_index.md b/daprdocs/content/en/getting-started/quickstarts/_index.md index 39c106fcd..9027c32a8 100644 --- a/daprdocs/content/en/getting-started/quickstarts/_index.md +++ b/daprdocs/content/en/getting-started/quickstarts/_index.md @@ -25,7 +25,7 @@ Hit the ground running with our Dapr quickstarts, complete with code samples aim | [Service Invocation]({{< ref serviceinvocation-quickstart.md >}}) | Call a method on another service using the service invocation API. | | [Publish and Subscribe]({{< ref pubsub-quickstart.md >}}) | Send and receive messages using the publish and subscribe API. | | [State Management]({{< ref statemanagement-quickstart.md >}}) | Create stateful applications using the state management API. | -| Bindings | Coming soon. | +| [Bindings]({{< ref bindings-quickstart.md >}}) | Use Dapr's input and output bindings to schedule a database insert job. | | Actors | Coming soon. | | Observability | Coming soon. | | Secrets Management | Coming soon. | diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md new file mode 100644 index 000000000..4c3f52f53 --- /dev/null +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -0,0 +1,778 @@ +--- +type: docs +title: "Quickstart: Bindings" +linkTitle: "Dapr Bindings" +weight: 70 +description: "Get started with Dapr's Binding building block" +--- + +Let's take a look at Dapr's [Binding building block]({{< ref bindings >}}). In this Quickstart, you will schedule a script to run every 10 seconds using an input [Cron](https://docs.dapr.io/reference/components-reference/supported-bindings/cron/) binding. The script will process a Json file and output data to a SQL database using the [PostgreSQL](https://docs.dapr.io/reference/components-reference/supported-bindings/postgres) Dapr binding. + +Using bindings, you can trigger your app with events coming in from external systems, or interface with external systems. Bindings provide several benefits for you and your code: + - Remove the complexities of connecting to, and polling from, messaging systems such as queues and message buses. + - Focus on business logic and not implementation details of how to interact with a system. + - Keep your code free from SDKs or libraries. + - Handle retries and failure recovery. + - Switch between bindings at run time. + - Build portable applications where environment-specific bindings are set-up and no code changes are required. + +For a specific example, bindings would allow your microservice to respond to incoming Twilio/SMS messages without adding or configuring a third-party Twilio SDK, worrying about polling from Twilio (or using websockets, etc.). + + + +Select your preferred language-specific Dapr SDK before proceeding with the Quickstart. + +{{< tabs "Python" "JavaScript" ".NET" "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 we've provided in our Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/bindings). +```bash +git clone https://github.com/dapr/quickstarts.git +``` +### Step 2: Run PostgreSQL Docker Container Locally + +In order to run the PostgreSQL bindings quickstart locally, you will run the [PostgreSQL instance](https://www.postgresql.org/) in a docker container on your machine. + +To run the container locally, run: + +```bash +docker run --name sql_db -p 5432:5432 -e POSTGRES_PASSWORD=admin -e POSTGRES_USER=admin -d postgres +``` + +To see the container running locally, run: +```bash +docker ps +``` + +The output should be similar to this: +```bash +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +55305d1d378b postgres "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:5432->5432/tcp sql_db +``` + +### Step 3: Setup the database schema + +Connect to the local PostgreSQL instance. +```bash +docker exec -i -t sql_db psql --username admin -p 5432 -h localhost --no-password +``` +This will launch the PostgreSQL cli. +```bash +psql (14.2 (Debian 14.2-1.pgdg110+1)) +Type "help" for help. + +admin=# +``` +Create a new `orders` database. +```bash +create database orders; +``` +Connect to the new database and create the `orders` table. +```bash +\c orders; +create table orders ( orderid int, customer text, price float ); select * from orders; +``` + +### Step 4: Schedule a Cron job and write to the database + +In a terminal window, navigate to the `sdk` directory. + +```bash +cd bindings/python/sdk +``` + +Install the dependencies: + +```bash +pip3 install -r requirements.txt +``` + +Run the `python-quickstart-binding-sdk` service alongside a Dapr sidecar. + +```bash +dapr run --app-id python-quickstart-binding-sdk --app-protocol grpc --app-port 50051 --components-path ../../components python3 batch.py +``` +The `python-quickstart-binding-sdk` uses the PostgreSQL Output Binding defined in the [`bindings.yaml`]({{< ref "#bindingsyaml-component-file" >}}) component to insert the `OrderId`, `Customer` and `Price` records into the `orders` table. This code is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). + +```python +def sql_output(order_line): + + with DaprClient() as d: + sqlCmd = 'insert into orders (orderid, customer, price) values ({}, \'{}\', {});'.format(order_line['orderid'], order_line['customer'], order_line['price']) + payload = { 'sql' : sqlCmd } + print(json.dumps(payload), flush=True) + try: + d.invoke_binding(binding_name=sql_binding, operation='exec', binding_metadata=payload, data='') + except Exception as e: + print(e, flush=True) +``` + +### Step 5: View the Output Binding log + +Notice, as specified above, the code invokes the Output Binding with the `OrderId`, `Customer` and `Price` as a payload. + +Output Binding `print` statement output: +``` +== APP == {"sql": "insert into orders (orderid, customer, price) values (1, 'John Smith', 100.32);"} +== APP == {"sql": "insert into orders (orderid, customer, price) values (2, 'Jane Bond', 15.4);"} +== APP == {"sql": "insert into orders (orderid, customer, price) values (3, 'Tony James', 35.56);"} +``` + +### Step 6: Process the `orders.json` file on a schedule + +The `python-quickstart-binding-sdk` uses the Cron Input Binding defined in the [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) component to process a json file containing order information. + +```python +@app.binding(cron_bindingName) +def cron_binding(request: BindingRequest): + + json_file = open("../../orders.json","r") + json_array = json.load(json_file) + + for order_line in json_array['orders']: + sql_output(order_line) + + json_file.close() + return 'Cron event processed' +``` + +#### `cron.yaml` component file + +When you execute the `dapr run` command and specify the location of the component file, the Dapr sidecar initiates the Cron [Binding building block]({{< ref bindings >}}) and calls the binding endpoint (`batch`) every 10 seconds. + +The Cron `cron.yaml` file included for this Quickstart contains the following: + +```yaml +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: batch + namespace: quickstarts +spec: + type: bindings.cron + version: v1 + metadata: + - name: schedule + value: "@every 10s" # valid cron schedule +``` + +**Note:** The `metadata` section of `cron.yaml` contains a [cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding will be invoked. + +#### `bindings.yaml` component file + +When you execute the `dapr run` command and specify the location of the component file, the Dapr sidecar initiates the PostgreSQL [Binding building block](/reference/components-reference/supported-bindings/postgres/) and connects to PostgreSQL using the settings specified in the `bindings.yaml` file. + +With the `bindings.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. + +The PostgreSQL `bindings.yaml` file included for this Quickstart contains the following: + +```yaml +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: SqlDB + namespace: quickstarts +spec: + type: bindings.postgres + version: v1 + metadata: + - name: url # Required + value: "user=admin password=admin host=localhost port=5432 dbname=orders pool_min_conns=1 pool_max_conns=10" +``` + +In the YAML file: + +- `spec/type` specifies that PostgreSQL is used for this binding. +- `spec/metadata` defines the connection to the PostgreSQL instance used by the component. + +{{% /codetab %}} + + +{{% codetab %}} + +### Pre-requisites + +For this example, you will need: + +- [Dapr CLI and initialized environment](https://docs.dapr.io/getting-started). +- [Latest Node.js installed](https://nodejs.org/download/). +- [Docker Desktop](https://www.docker.com/products/docker-desktop) + +### Step 1: Set up the environment + +Clone the [sample we've provided in our Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/bindings). +```bash +git clone https://github.com/dapr/quickstarts.git +``` + +### Step 2: Run PostgreSQL Docker Container Locally + +In order to run the PostgreSQL bindings quickstart locally, you will run the [PostgreSQL instance](https://www.postgresql.org/) in a docker container on your machine. + +To run the container locally, run: + +```bash +docker run --name sql_db -p 5432:5432 -e POSTGRES_PASSWORD=admin -e POSTGRES_USER=admin -d postgres +``` + +To see the container running locally, run: +```bash +docker ps +``` + +The output should be similar to this: +```bash +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +55305d1d378b postgres "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:5432->5432/tcp sql_db +``` + +### Step 3: Setup the database schema + +Connect to the local PostgreSQL instance. +```bash +docker exec -i -t sql_db psql --username admin -p 5432 -h localhost --no-password +``` +This will launch the PostgreSQL cli. +```bash +psql (14.2 (Debian 14.2-1.pgdg110+1)) +Type "help" for help. + +admin=# +``` +Create a new `orders` database. +```bash +create database orders; +``` +Connect to the new database and create the `orders` table. +```bash +\c orders; +create table orders ( orderid int, customer text, price float ); select * from orders; +``` + +### Step 4: Schedule a Cron job and write to the database + +In a terminal window, navigate to the `sdk` directory. + +```bash +cd bindings/javascript/sdk +``` + +Install the dependencies: + +```bash +npm install +``` + +Run the `javascript-quickstart-binding-sdk` service alongside a Dapr sidecar. + +```bash +dapr run --app-id javascript-quickstart-binding-sdk --app-port 3500 --dapr-http-port 5051 node batch.js --components-path ../../components +``` +The `javascript-quickstart-binding-sdk` uses the PostgreSQL Output Binding defined in the [`bindings.yaml`]({{< ref "#bindingsyaml-component-file" >}}) component to insert the `OrderId`, `Customer` and `Price` records into the `orders` table. This code is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). + +```js +async function processBatch(){ + const loc = '../../orders.json'; + fs.readFile(loc, 'utf8', (err, data) => { + const orders = JSON.parse(data).orders; + orders.forEach(order => { + let sqlCmd = `insert into orders (orderid, customer, price) values (${order.orderid}, '${order.customer}', ${order.price});`; + let payload = `{ "sql": "${sqlCmd}" } `; + console.log(payload); + client.binding.send(postgresBindingName, "exec", "", JSON.parse(payload)); + }); + console.log('Finished processing batch'); + }); + return 0; +} +``` + +### Step 5: View the Output Binding log + +Notice, as specified above, the code invokes the Output Binding with the `OrderId`, `Customer` and `Price` as a payload. + +Output Binding `console.log` statement output: +``` +== APP == [Dapr-JS] Server Started +== APP == { "sql": "insert into orders (orderid, customer, price) values (1, 'John Smith', 100.32);" } +== APP == { "sql": "insert into orders (orderid, customer, price) values (2, 'Jane Bond', 15.4);" } +== APP == { "sql": "insert into orders (orderid, customer, price) values (3, 'Tony James', 35.56);" } +== APP == Finished processing batch +``` + +### Step 6: Process the `orders.json` file on a schedule + +The `javascript-quickstart-binding-sdk` uses the Cron Input Binding defined in the [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) component to process a json file containing order information. + +```js +const server = new DaprServer(serverHost, serverPort, daprHost, daprPort); + +async function start() { + await server.binding.receive(cronBindingName,processBatch); + await server.start(); +} +``` + +#### `cron.yaml` component file + +When you execute the `dapr run` command and specify the location of the component file, the Dapr sidecar initiates the Cron [Binding building block]({{< ref bindings >}}) and calls the binding endpoint (`batch`) every 10 seconds. + +The Cron `cron.yaml` file included for this Quickstart contains the following: + +```yaml +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: batch + namespace: quickstarts +spec: + type: bindings.cron + version: v1 + metadata: + - name: schedule + value: "@every 10s" # valid cron schedule +``` + +**Note:** The `metadata` section of `cron.yaml` contains a [cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding will be invoked. + +#### `bindings.yaml` component file + +When you execute the `dapr run` command and specify the location of the component file, the Dapr sidecar initiates the PostgreSQL [Binding building block](/reference/components-reference/supported-bindings/postgres/) and connects to PostgreSQL using the settings specified in the `bindings.yaml` file. + +With the `bindings.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. + +The PostgreSQL `bindings.yaml` file included for this Quickstart contains the following: + +```yaml +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: SqlDB + namespace: quickstarts +spec: + type: bindings.postgres + version: v1 + metadata: + - name: url # Required + value: "user=admin password=admin host=localhost port=5432 dbname=orders pool_min_conns=1 pool_max_conns=10" +``` + +In the YAML file: + +- `spec/type` specifies that PostgreSQL is used for this binding. +- `spec/metadata` defines the connection to the PostgreSQL instance used by the component. + +{{% /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 we've provided in our Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/bindings). +```bash +git clone https://github.com/dapr/quickstarts.git +``` + +### Step 2: Run PostgreSQL Docker Container Locally + +In order to run the PostgreSQL bindings quickstart locally, you will run the [PostgreSQL instance](https://www.postgresql.org/) in a docker container on your machine. + +To run the container locally, run: + +```bash +docker run --name sql_db -p 5432:5432 -e POSTGRES_PASSWORD=admin -e POSTGRES_USER=admin -d postgres +``` + +To see the container running locally, run: +```bash +docker ps +``` + +The output should be similar to this: +```bash +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +55305d1d378b postgres "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:5432->5432/tcp sql_db +``` + +### Step 3: Setup the database schema + +Connect to the local PostgreSQL instance. +```bash +docker exec -i -t sql_db psql --username admin -p 5432 -h localhost --no-password +``` +This will launch the PostgreSQL cli. +```bash +psql (14.2 (Debian 14.2-1.pgdg110+1)) +Type "help" for help. + +admin=# +``` +Create a new `orders` database. +```bash +create database orders; +``` +Connect to the new database and create the `orders` table. +```bash +\c orders; +create table orders ( orderid int, customer text, price float ); select * from orders; +``` + +### Step 4: Schedule a Cron job and write to the database + +In a terminal window, navigate to the `sdk` directory. + +```bash +cd bindings/csharp/sdk +``` + +Install the dependencies: + +```bash +dotnet restore +dotnet build batch.csproj +``` + +Run the `csharp-quickstart-binding-sdk` service alongside a Dapr sidecar. + +```bash +dapr run --app-id csharp-quickstart-binding-sdk --app-port 7001 --components-path ../../components -- dotnet run --project batch.csproj +``` +The `csharp-quickstart-binding-sdk` uses the PostgreSQL Output Binding defined in the [`bindings.yaml`]({{< ref "#bindingsyaml-component-file" >}}) component to insert the `OrderId`, `Customer` and `Price` records into the `orders` table. This code is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). + +```cs +foreach( Order ord in ordersArr.orders){ + var sqlText = $"insert into orders (orderid, customer, price) values ({ord.OrderId}, '{ord.Customer}', {ord.Price});"; + var command = new Dictionary(){ + {"sql", + sqlText} + }; + await client.InvokeBindingAsync(sqlBindingName, "exec", command,command); + Console.WriteLine(sqlText); +} +``` + +### Step 5: View the Output Binding log + +Notice, as specified above, the code invokes the Output Binding with the `OrderId`, `Customer` and `Price` as a payload. + +Output Binding `Console.WriteLine` statement output: +``` +== APP == insert into orders (orderid, customer, price) values (1, 'John Smith', 100.32); +== APP == insert into orders (orderid, customer, price) values (2, 'Jane Bond', 15.4); +== APP == insert into orders (orderid, customer, price) values (3, 'Tony James', 35.56); +``` + +### Step 6: Process the `orders.json` file on a schedule + +The `csharp-quickstart-binding-sdk` uses the Cron Input Binding defined in the [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) component to process a json file containing order information. + +```cs +app.MapPost(cronBindingName, async () => { + + string text = File.ReadAllText("../../orders.json"); + var ordersArr = JsonSerializer.Deserialize(text); + using var client = new DaprClientBuilder().Build(); + ... + } +}); +``` + +#### `cron.yaml` component file + +When you execute the `dapr run` command and specify the location of the component file, the Dapr sidecar initiates the Cron [Binding building block]({{< ref bindings >}}) and calls the binding endpoint (`batch`) every 10 seconds. + +The Cron `cron.yaml` file included for this Quickstart contains the following: + +```yaml +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: batch + namespace: quickstarts +spec: + type: bindings.cron + version: v1 + metadata: + - name: schedule + value: "@every 10s" # valid cron schedule +``` + +**Note:** The `metadata` section of `cron.yaml` contains a [cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding will be invoked. + +#### `bindings.yaml` component file + +When you execute the `dapr run` command and specify the location of the component file, the Dapr sidecar initiates the PostgreSQL [Binding building block](/reference/components-reference/supported-bindings/postgres/) and connects to PostgreSQL using the settings specified in the `bindings.yaml` file. + +With the `bindings.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. + +The PostgreSQL `bindings.yaml` file included for this Quickstart contains the following: + +```yaml +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: SqlDB + namespace: quickstarts +spec: + type: bindings.postgres + version: v1 + metadata: + - name: url # Required + value: "user=admin password=admin host=localhost port=5432 dbname=orders pool_min_conns=1 pool_max_conns=10" +``` + +In the YAML file: + +- `spec/type` specifies that PostgreSQL is used for this binding. +- `spec/metadata` defines the connection to the PostgreSQL instance used by the component. + +{{% /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 we've provided in our Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/bindings). +```bash +git clone https://github.com/dapr/quickstarts.git +``` +### Step 2: Run PostgreSQL Docker Container Locally + +In order to run the PostgreSQL bindings quickstart locally, you will run the [PostgreSQL instance](https://www.postgresql.org/) in a docker container on your machine. + +To run the container locally, run: + +```bash +docker run --name sql_db -p 5432:5432 -e POSTGRES_PASSWORD=admin -e POSTGRES_USER=admin -d postgres +``` + +To see the container running locally, run: +```bash +docker ps +``` + +The output should be similar to this: +```bash +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +55305d1d378b postgres "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:5432->5432/tcp sql_db +``` + +### Step 3: Setup the database schema + +Connect to the local PostgreSQL instance. +```bash +docker exec -i -t sql_db psql --username admin -p 5432 -h localhost --no-password +``` +This will launch the PostgreSQL cli. +```bash +psql (14.2 (Debian 14.2-1.pgdg110+1)) +Type "help" for help. + +admin=# +``` +Create a new `orders` database. +```bash +create database orders; +``` +Connect to the new database and create the `orders` table. +```bash +\c orders; +create table orders ( orderid int, customer text, price float ); select * from orders; +``` + +### Step 4: Schedule a Cron job and write to the database + +In a terminal window, navigate to the `sdk` directory. + +```bash +cd bindings/go/sdk +``` + +Install the dependencies: + +```bash +go build batch.go +``` + +Run the `go-input-binding-sdk` service alongside a Dapr sidecar. + +```bash +dapr run --app-id go-input-binding-sdk --app-port 6002 --dapr-http-port 6003 --dapr-grpc-port 60002 go run batch.go --components-path ../../components +``` +The `go-input-binding-sdk` uses the PostgreSQL Output Binding defined in the [`bindings.yaml`]({{< ref "#bindingsyaml-component-file" >}}) component to insert the `OrderId`, `Customer` and `Price` records into the `orders` table. This code is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). + +```go +func sqlBindings(order Order) (err error) { + + bindingName := "SqlDB" + + client, err := dapr.NewClient() + if err != nil { + return err + } + + ctx := context.Background() + + sqlCmd := fmt.Sprintf("insert into orders (orderid, customer, price) values (%d, '%s', %s);", order.OrderId, order.Customer, strconv.FormatFloat(order.Price, 'f', 2, 64)) + fmt.Println(sqlCmd) + in := &dapr.InvokeBindingRequest{ + Name: bindingName, + Operation: "exec", + Data: []byte(""), + Metadata: map[string]string{"sql": sqlCmd}, + } + err = client.InvokeOutputBinding(ctx, in) + if err != nil { + return err + } + return nil +} +``` + +### Step 5: View the Output Binding log + +Notice, as specified above, the code invokes the Output Binding with the `OrderId`, `Customer` and `Price` as a payload. + +Output Binding `console.log` statement output: +``` +== APP == The File is opened successfully... +== APP == dapr client initializing for: 127.0.0.1:60002 +== APP == insert into orders (orderid, customer, price) values (1, 'John Smith', 100.32); +== APP == insert into orders (orderid, customer, price) values (2, 'Jane Bond', 15.40); +== APP == insert into orders (orderid, customer, price) values (3, 'Tony James', 35.56); +== APP == Finished processing batch +``` + +### Step 6: Process the `orders.json` file on a schedule + +The `go-input-binding-sdk` uses the Cron Input Binding defined in the [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) component to process a json file containing order information. + +```go +func processCron(w http.ResponseWriter, r *http.Request) { + + fileContent, err := os.Open("../../orders.json") + if err != nil { + log.Fatal(err) + return + } + + fmt.Println("The File is opened successfully...") + + defer fileContent.Close() + + byteResult, _ := ioutil.ReadAll(fileContent) + + var orders Orders + + json.Unmarshal(byteResult, &orders) + + for i := 0; i < len(orders.Orders); i++ { + err := sqlBindings(orders.Orders[i]) + if err != nil { + log.Fatal(err) + os.Exit(1) + } + } + fmt.Println("Finished processing batch") + os.Exit(0) +} + +``` + +#### `cron.yaml` component file + +When you execute the `dapr run` command and specify the location of the component file, the Dapr sidecar initiates the Cron [Binding building block]({{< ref bindings >}}) and calls the binding endpoint (`batch`) every 10 seconds. + +The Cron `cron.yaml` file included for this Quickstart contains the following: + +```yaml +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: batch + namespace: quickstarts +spec: + type: bindings.cron + version: v1 + metadata: + - name: schedule + value: "@every 10s" # valid cron schedule +``` + +**Note:** The `metadata` section of `cron.yaml` contains a [cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding will be invoked. + +#### `bindings.yaml` component file + +When you execute the `dapr run` command and specify the location of the component file, the Dapr sidecar initiates the PostgreSQL [Binding building block](/reference/components-reference/supported-bindings/postgres/) and connects to PostgreSQL using the settings specified in the `bindings.yaml` file. + +With the `bindings.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. + +The PostgreSQL `bindings.yaml` file included for this Quickstart contains the following: + +```yaml +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: SqlDB + namespace: quickstarts +spec: + type: bindings.postgres + version: v1 + metadata: + - name: url # Required + value: "user=admin password=admin host=localhost port=5432 dbname=orders pool_min_conns=1 pool_max_conns=10" +``` + +In the YAML file: + +- `spec/type` specifies that PostgreSQL is used for this binding. +- `spec/metadata` defines the connection to the PostgreSQL instance used by the component. + +{{% /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.gg/22ZtJrNe). + +## Next steps + +- Use Dapr Bindings with HTTP instead of an SDK. + - [Python](https://github.com/dapr/quickstarts/tree/master/bindings/python/http) + - [JavaScript](https://github.com/dapr/quickstarts/tree/master/bindings/javascript/http) + - [.NET](https://github.com/dapr/quickstarts/tree/master/bindings/csharp/http) + - [Go](https://github.com/dapr/quickstarts/tree/master/bindings/go/http) +- Learn more about [Binding building block]({{< ref bindings >}}) + +{{< button text="Explore Dapr tutorials >>" page="getting-started/tutorials/_index.md" >}} From 1e5a489e91834b26e902d8c9e164514e306ecf22 Mon Sep 17 00:00:00 2001 From: Paul Yuknewicz Date: Wed, 15 Jun 2022 11:46:16 -0700 Subject: [PATCH 02/42] Updated python to be shorter and conform to code Signed-off-by: Paul Yuknewicz --- .../quickstarts/bindings-quickstart.md | 141 ++++++++---------- 1 file changed, 65 insertions(+), 76 deletions(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index 4c3f52f53..708a1252f 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -6,17 +6,13 @@ weight: 70 description: "Get started with Dapr's Binding building block" --- -Let's take a look at Dapr's [Binding building block]({{< ref bindings >}}). In this Quickstart, you will schedule a script to run every 10 seconds using an input [Cron](https://docs.dapr.io/reference/components-reference/supported-bindings/cron/) binding. The script will process a Json file and output data to a SQL database using the [PostgreSQL](https://docs.dapr.io/reference/components-reference/supported-bindings/postgres) Dapr binding. +Let's take a look at Dapr's [Binding building block]({{< ref bindings >}}). In this Quickstart, you will schedule a batch script to run every 10 seconds using an input [Cron](https://docs.dapr.io/reference/components-reference/supported-bindings/cron/) binding. The script will process a Json file and output data to an external SQL database using the [PostgreSQL](https://docs.dapr.io/reference/components-reference/supported-bindings/postgres) Dapr binding. -Using bindings, you can trigger your app with events coming in from external systems, or interface with external systems. Bindings provide several benefits for you and your code: - - Remove the complexities of connecting to, and polling from, messaging systems such as queues and message buses. - - Focus on business logic and not implementation details of how to interact with a system. - - Keep your code free from SDKs or libraries. - - Handle retries and failure recovery. - - Switch between bindings at run time. - - Build portable applications where environment-specific bindings are set-up and no code changes are required. - -For a specific example, bindings would allow your microservice to respond to incoming Twilio/SMS messages without adding or configuring a third-party Twilio SDK, worrying about polling from Twilio (or using websockets, etc.). +Using bindings in Dapr, you can easily interface with a number of external systems. E.g. you can trigger your app with events coming in from external systems, or interface with external systems. Bindings provide several benefits for you and your code: + - Remove the complexities of connecting to, and polling from, messaging systems such as system resources, database, queues and message buses. + - Focus on business logic and not implementation details of how to interact with a system, keeping your code free from SDKs or SDK specific logic. + - Add best practices like resiliency to your interactions with external systems. + - Build portable applications where environment-specific bindings are set-up and no code changes are required to switch between bindings at runtime. @@ -42,12 +38,14 @@ git clone https://github.com/dapr/quickstarts.git ``` ### Step 2: Run PostgreSQL Docker Container Locally -In order to run the PostgreSQL bindings quickstart locally, you will run the [PostgreSQL instance](https://www.postgresql.org/) in a docker container on your machine. +In order to run the PostgreSQL bindings quickstart locally, you will run the [PostgreSQL instance](https://www.postgresql.org/) in a docker container on your machine. For convenience, we provided a Docker Compose file to customize, build, run, and initialize the `postgres` container with a default `orders` table for you locally. -To run the container locally, run: +In a terminal window, from the root of the Quickstarts clone directory +navigate to the `bindings\db` directory. +To run the container locally, in another new terminal window: ```bash -docker run --name sql_db -p 5432:5432 -e POSTGRES_PASSWORD=admin -e POSTGRES_USER=admin -d postgres +docker compose up ``` To see the container running locally, run: @@ -61,35 +59,12 @@ CONTAINER ID IMAGE COMMAND CREATED STATUS 55305d1d378b postgres "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:5432->5432/tcp sql_db ``` -### Step 3: Setup the database schema +### Step 3: Schedule a Cron job and write to the database -Connect to the local PostgreSQL instance. -```bash -docker exec -i -t sql_db psql --username admin -p 5432 -h localhost --no-password -``` -This will launch the PostgreSQL cli. -```bash -psql (14.2 (Debian 14.2-1.pgdg110+1)) -Type "help" for help. - -admin=# -``` -Create a new `orders` database. -```bash -create database orders; -``` -Connect to the new database and create the `orders` table. -```bash -\c orders; -create table orders ( orderid int, customer text, price float ); select * from orders; -``` - -### Step 4: Schedule a Cron job and write to the database - -In a terminal window, navigate to the `sdk` directory. +In a new terminal window, navigate to the `quickstarts/bindings/python/sdk` directory. ```bash -cd bindings/python/sdk +cd quickstarts/bindings/python/sdk ``` Install the dependencies: @@ -103,61 +78,75 @@ Run the `python-quickstart-binding-sdk` service alongside a Dapr sidecar. ```bash dapr run --app-id python-quickstart-binding-sdk --app-protocol grpc --app-port 50051 --components-path ../../components python3 batch.py ``` -The `python-quickstart-binding-sdk` uses the PostgreSQL Output Binding defined in the [`bindings.yaml`]({{< ref "#bindingsyaml-component-file" >}}) component to insert the `OrderId`, `Customer` and `Price` records into the `orders` table. This code is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). + +Code inside the `process_batch` function is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks simply like a route getting called via HTTP POST in your Flask application, which is called by the Dapr sidecar. ```python -def sql_output(order_line): - - with DaprClient() as d: - sqlCmd = 'insert into orders (orderid, customer, price) values ({}, \'{}\', {});'.format(order_line['orderid'], order_line['customer'], order_line['price']) - payload = { 'sql' : sqlCmd } - print(json.dumps(payload), flush=True) - try: - d.invoke_binding(binding_name=sql_binding, operation='exec', binding_metadata=payload, data='') - except Exception as e: - print(e, flush=True) +# Triggered by Dapr input binding +@app.route('/' + cron_binding_name, methods=['POST']) +def process_batch(): ``` -### Step 5: View the Output Binding log +The `python-quickstart-binding-sdk` uses the PostgreSQL Output Binding defined in the [`bindings.yaml`]({{< ref "#bindingsyaml-component-file" >}}) component to insert the `OrderId`, `Customer` and `Price` records into the `orders` table. + +```python + with DaprClient() as d: + sqlCmd = ('insert into orders (orderid, customer, price) values' + + '(%s, \'%s\', %s)' % (order_line['orderid'], + order_line['customer'], + order_line['price'])) + payload = {'sql': sqlCmd} + + print(sqlCmd, flush=True) + + try: + # Insert order using Dapr output binding via HTTP Post + resp = d.invoke_binding(binding_name=sql_binding, operation='exec', + binding_metadata=payload, data='') + return resp + except Exception as e: + print(e, flush=True) + raise SystemExit(e) +``` + +### Step 4: View the output of the job Notice, as specified above, the code invokes the Output Binding with the `OrderId`, `Customer` and `Price` as a payload. -Output Binding `print` statement output: +Output Binding `print` statement output in your application: ``` == APP == {"sql": "insert into orders (orderid, customer, price) values (1, 'John Smith', 100.32);"} == APP == {"sql": "insert into orders (orderid, customer, price) values (2, 'Jane Bond', 15.4);"} == APP == {"sql": "insert into orders (orderid, customer, price) values (3, 'Tony James', 35.56);"} ``` -### Step 6: Process the `orders.json` file on a schedule +You can also see the same data has been inserted into the database. To inspect the `postgres` container, run the following in a new terminal to start the interactive Postgres CLI -The `python-quickstart-binding-sdk` uses the Cron Input Binding defined in the [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) component to process a json file containing order information. - -```python -@app.binding(cron_bindingName) -def cron_binding(request: BindingRequest): - - json_file = open("../../orders.json","r") - json_array = json.load(json_file) - - for order_line in json_array['orders']: - sql_output(order_line) - - json_file.close() - return 'Cron event processed' +```bash +docker exec -i -t postgres psql --username postgres -p 5432 -h localhost --no-password ``` -#### `cron.yaml` component file +At the `admin=#` prompt, change to the `orders` table: +```bash +\c orders; +``` + +At the `orders=#` prompt, select all rows: +```bash +select * from orders; +``` + +#### `components\binding-cron.yaml` component file When you execute the `dapr run` command and specify the location of the component file, the Dapr sidecar initiates the Cron [Binding building block]({{< ref bindings >}}) and calls the binding endpoint (`batch`) every 10 seconds. -The Cron `cron.yaml` file included for this Quickstart contains the following: +The Cron `binding-cron.yaml` file included for this Quickstart contains the following: ```yaml apiVersion: dapr.io/v1alpha1 kind: Component metadata: - name: batch + name: cron namespace: quickstarts spec: type: bindings.cron @@ -167,21 +156,21 @@ spec: value: "@every 10s" # valid cron schedule ``` -**Note:** The `metadata` section of `cron.yaml` contains a [cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding will be invoked. +**Note:** The `metadata` section of `binding-cron.yaml` contains a [cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding will be invoked. -#### `bindings.yaml` component file +#### `component\bindings-postgres.yaml` component file -When you execute the `dapr run` command and specify the location of the component file, the Dapr sidecar initiates the PostgreSQL [Binding building block](/reference/components-reference/supported-bindings/postgres/) and connects to PostgreSQL using the settings specified in the `bindings.yaml` file. +When you execute the `dapr run` command and specify the location of the component file, the Dapr sidecar initiates the PostgreSQL [Binding building block](/reference/components-reference/supported-bindings/postgres/) and connects to PostgreSQL using the settings specified in the `bindings-postgres.yaml` file. -With the `bindings.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. +With the `bindings-postgres.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. -The PostgreSQL `bindings.yaml` file included for this Quickstart contains the following: +The PostgreSQL `bindings-postgres.yaml` file included for this Quickstart contains the following: ```yaml apiVersion: dapr.io/v1alpha1 kind: Component metadata: - name: SqlDB + name: sqldb namespace: quickstarts spec: type: bindings.postgres From 1dc60a47a87bfcfcadf75038116d1e292d9e4bc1 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Thu, 16 Jun 2022 15:33:57 -0500 Subject: [PATCH 03/42] revisions based on changes to code; add image Signed-off-by: Hannah Hunter --- .../en/getting-started/quickstarts/_index.md | 2 +- .../quickstarts/bindings-quickstart.md | 648 ++++++++++-------- .../bindings-quickstart.png | Bin 0 -> 23076 bytes 3 files changed, 354 insertions(+), 296 deletions(-) create mode 100644 daprdocs/static/images/bindings-quickstart/bindings-quickstart.png diff --git a/daprdocs/content/en/getting-started/quickstarts/_index.md b/daprdocs/content/en/getting-started/quickstarts/_index.md index c01d2851f..cd4a5dff7 100644 --- a/daprdocs/content/en/getting-started/quickstarts/_index.md +++ b/daprdocs/content/en/getting-started/quickstarts/_index.md @@ -26,7 +26,7 @@ Hit the ground running with our Dapr quickstarts, complete with code samples aim | [State Management]({{< ref statemanagement-quickstart.md >}}) | Create stateful applications using the state management API. | | [Publish and Subscribe]({{< ref pubsub-quickstart.md >}}) | Send and receive messages using the publish and subscribe API. | | [Secrets Management]({{< ref secrets-quickstart.md >}}) | Retrieve secrets in the application code from a configured secret store using the secrets management API. | -| [Bindings]({{< ref bindings-quickstart.md >}}) | Use Dapr's input and output bindings to schedule a database insert job. | +| [Bindings]({{< ref bindings-quickstart.md >}}) | Schedule a database insert job using the input and output bindings API. | | Actors | Coming soon. | | Observability | Coming soon. | | Configuration | Coming soon. | \ No newline at end of file diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index 708a1252f..9a7469b0d 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -1,20 +1,19 @@ --- type: docs -title: "Quickstart: Bindings" -linkTitle: "Dapr Bindings" +title: "Quickstart: Input & Output Bindings" +linkTitle: "Bindings" weight: 70 description: "Get started with Dapr's Binding building block" --- -Let's take a look at Dapr's [Binding building block]({{< ref bindings >}}). In this Quickstart, you will schedule a batch script to run every 10 seconds using an input [Cron](https://docs.dapr.io/reference/components-reference/supported-bindings/cron/) binding. The script will process a Json file and output data to an external SQL database using the [PostgreSQL](https://docs.dapr.io/reference/components-reference/supported-bindings/postgres) Dapr binding. +Let's take a look at Dapr's [Bindings building block]({{< ref bindings >}}). Using bindings, you can: -Using bindings in Dapr, you can easily interface with a number of external systems. E.g. you can trigger your app with events coming in from external systems, or interface with external systems. Bindings provide several benefits for you and your code: - - Remove the complexities of connecting to, and polling from, messaging systems such as system resources, database, queues and message buses. - - Focus on business logic and not implementation details of how to interact with a system, keeping your code free from SDKs or SDK specific logic. - - Add best practices like resiliency to your interactions with external systems. - - Build portable applications where environment-specific bindings are set-up and no code changes are required to switch between bindings at runtime. +- Trigger your app with events coming in from external systems. +- Interface with external systems. - +In this Quickstart, you will schedule a batch script to run every 10 seconds using an input [Cron](https://docs.dapr.io/reference/components-reference/supported-bindings/cron/) binding. The script will process a JSON file and output data to an external SQL database using the [PostgreSQL](https://docs.dapr.io/reference/components-reference/supported-bindings/postgres) Dapr binding. + + Select your preferred language-specific Dapr SDK before proceeding with the Quickstart. @@ -33,27 +32,35 @@ For this example, you will need: ### Step 1: Set up the environment Clone the [sample we've provided in our Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/bindings). + ```bash git clone https://github.com/dapr/quickstarts.git ``` -### Step 2: Run PostgreSQL Docker Container Locally -In order to run the PostgreSQL bindings quickstart locally, you will run the [PostgreSQL instance](https://www.postgresql.org/) in a docker container on your machine. For convenience, we provided a Docker Compose file to customize, build, run, and initialize the `postgres` container with a default `orders` table for you locally. +### Step 2: Run PostgreSQL Docker container locally -In a terminal window, from the root of the Quickstarts clone directory -navigate to the `bindings\db` directory. +You will run the [PostgreSQL instance](https://www.postgresql.org/) locally in a Docker container on your machine. The Quickstart sample includes a Docker Compose file to locally customize, build, run, and initialize the `postgres` container with a default `orders` table. + +In a terminal window, from the root of the Quickstarts clone directory, navigate to the `bindings\db` directory. + +```bash +cd quickstarts/bindings/db +``` + +Run the following command to set up the container: -To run the container locally, in another new terminal window: ```bash docker compose up ``` -To see the container running locally, run: +Verify that the container is running locally. + ```bash docker ps ``` -The output should be similar to this: +The output should include: + ```bash CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 55305d1d378b postgres "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:5432->5432/tcp sql_db @@ -61,7 +68,7 @@ CONTAINER ID IMAGE COMMAND CREATED STATUS ### Step 3: Schedule a Cron job and write to the database -In a new terminal window, navigate to the `quickstarts/bindings/python/sdk` directory. +In a new terminal window, navigate to the SDK directory. ```bash cd quickstarts/bindings/python/sdk @@ -76,10 +83,10 @@ pip3 install -r requirements.txt Run the `python-quickstart-binding-sdk` service alongside a Dapr sidecar. ```bash -dapr run --app-id python-quickstart-binding-sdk --app-protocol grpc --app-port 50051 --components-path ../../components python3 batch.py +dapr run --app-id python-quickstart-binding-sdk --app-port 50051 --components-path ../../components python3 batch.py ``` -Code inside the `process_batch` function is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks simply like a route getting called via HTTP POST in your Flask application, which is called by the Dapr sidecar. +The code inside the `process_batch` function is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks like a route called via HTTP POST in your Flask application by the Dapr sidecar. ```python # Triggered by Dapr input binding @@ -87,58 +94,80 @@ Code inside the `process_batch` function is executed every 10 seconds (defined i def process_batch(): ``` -The `python-quickstart-binding-sdk` uses the PostgreSQL Output Binding defined in the [`bindings.yaml`]({{< ref "#bindingsyaml-component-file" >}}) component to insert the `OrderId`, `Customer` and `Price` records into the `orders` table. +The `python-quickstart-binding-sdk` service uses the PostgreSQL output binding defined in the [`bindings.yaml`]({{< ref "#bindingsyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. ```python - with DaprClient() as d: - sqlCmd = ('insert into orders (orderid, customer, price) values' + - '(%s, \'%s\', %s)' % (order_line['orderid'], - order_line['customer'], - order_line['price'])) - payload = {'sql': sqlCmd} +with DaprClient() as d: + sqlCmd = ('insert into orders (orderid, customer, price) values' + + '(%s, \'%s\', %s)' % (order_line['orderid'], + order_line['customer'], + order_line['price'])) + payload = {'sql': sqlCmd} - print(sqlCmd, flush=True) + print(sqlCmd, flush=True) - try: - # Insert order using Dapr output binding via HTTP Post - resp = d.invoke_binding(binding_name=sql_binding, operation='exec', - binding_metadata=payload, data='') - return resp - except Exception as e: - print(e, flush=True) - raise SystemExit(e) + try: + # Insert order using Dapr output binding via HTTP Post + resp = d.invoke_binding(binding_name=sql_binding, operation='exec', + binding_metadata=payload, data='') + return resp + except Exception as e: + print(e, flush=True) + raise SystemExit(e) ``` ### Step 4: View the output of the job -Notice, as specified above, the code invokes the Output Binding with the `OrderId`, `Customer` and `Price` as a payload. +Notice, as specified above, the code invokes the Output Binding with the `OrderId`, `Customer`, and `Price` as a payload. + +Your output binding's `print` statement output: -Output Binding `print` statement output in your application: ``` == APP == {"sql": "insert into orders (orderid, customer, price) values (1, 'John Smith', 100.32);"} == APP == {"sql": "insert into orders (orderid, customer, price) values (2, 'Jane Bond', 15.4);"} == APP == {"sql": "insert into orders (orderid, customer, price) values (3, 'Tony James', 35.56);"} ``` -You can also see the same data has been inserted into the database. To inspect the `postgres` container, run the following in a new terminal to start the interactive Postgres CLI +In a new terminal, verify the same data has been inserted into the database. Navigate to the `bindings/db` directory. + +```bash +cd quickstarts/bindings/db +``` + +Run the following to start the interactive Postgres CLI: ```bash docker exec -i -t postgres psql --username postgres -p 5432 -h localhost --no-password ``` At the `admin=#` prompt, change to the `orders` table: + ```bash \c orders; ``` At the `orders=#` prompt, select all rows: + ```bash select * from orders; ``` +The output should look like this: + +``` + orderid | customer | price +---------+------------+-------- + 1 | John Smith | 100.32 + 2 | Jane Bond | 15.4 + 3 | Tony James | 35.56 +``` + #### `components\binding-cron.yaml` component file -When you execute the `dapr run` command and specify the location of the component file, the Dapr sidecar initiates the Cron [Binding building block]({{< ref bindings >}}) and calls the binding endpoint (`batch`) every 10 seconds. +When you execute the `dapr run` command and specify the component path, the Dapr sidecar: + +- Initiates the Cron [Binding building block]({{< ref bindings >}}) +- Calls the binding endpoint (`batch`) every 10 seconds The Cron `binding-cron.yaml` file included for this Quickstart contains the following: @@ -156,11 +185,14 @@ spec: value: "@every 10s" # valid cron schedule ``` -**Note:** The `metadata` section of `binding-cron.yaml` contains a [cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding will be invoked. +**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding will be invoked. #### `component\bindings-postgres.yaml` component file -When you execute the `dapr run` command and specify the location of the component file, the Dapr sidecar initiates the PostgreSQL [Binding building block](/reference/components-reference/supported-bindings/postgres/) and connects to PostgreSQL using the settings specified in the `bindings-postgres.yaml` file. +When you execute the `dapr run` command and specify the component path, the Dapr sidecar: + +- Initiates the PostgreSQL [Binding building block]({{< ref /reference/components-reference/supported-bindings/postgres.md >}}) +- Connects to PostgreSQL using the settings specified in the `bindings-postgres.yaml` file With the `bindings-postgres.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. @@ -177,7 +209,7 @@ spec: version: v1 metadata: - name: url # Required - value: "user=admin password=admin host=localhost port=5432 dbname=orders pool_min_conns=1 pool_max_conns=10" + value: "user=postgres password=docker host=localhost port=5432 dbname=orders pool_min_conns=1 pool_max_conns=10" ``` In the YAML file: @@ -201,60 +233,46 @@ For this example, you will need: ### Step 1: Set up the environment Clone the [sample we've provided in our Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/bindings). + ```bash git clone https://github.com/dapr/quickstarts.git ``` -### Step 2: Run PostgreSQL Docker Container Locally +### Step 2: Run PostgreSQL Docker container locally -In order to run the PostgreSQL bindings quickstart locally, you will run the [PostgreSQL instance](https://www.postgresql.org/) in a docker container on your machine. +You will run the [PostgreSQL instance](https://www.postgresql.org/) locally in a Docker container on your machine. The Quickstart sample includes a Docker Compose file to locally customize, build, run, and initialize the `postgres` container with a default `orders` table. -To run the container locally, run: +In a terminal window, from the root of the Quickstarts clone directory, navigate to the `bindings\db` directory. ```bash -docker run --name sql_db -p 5432:5432 -e POSTGRES_PASSWORD=admin -e POSTGRES_USER=admin -d postgres +cd quickstarts/bindings/db ``` -To see the container running locally, run: +Run the following command to set up the container: + +```bash +docker compose up +``` + +Verify that the container is running locally. + ```bash docker ps ``` -The output should be similar to this: +The output should include: + ```bash CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 55305d1d378b postgres "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:5432->5432/tcp sql_db ``` -### Step 3: Setup the database schema +### Step 3: Schedule a Cron job and write to the database -Connect to the local PostgreSQL instance. -```bash -docker exec -i -t sql_db psql --username admin -p 5432 -h localhost --no-password -``` -This will launch the PostgreSQL cli. -```bash -psql (14.2 (Debian 14.2-1.pgdg110+1)) -Type "help" for help. - -admin=# -``` -Create a new `orders` database. -```bash -create database orders; -``` -Connect to the new database and create the `orders` table. -```bash -\c orders; -create table orders ( orderid int, customer text, price float ); select * from orders; -``` - -### Step 4: Schedule a Cron job and write to the database - -In a terminal window, navigate to the `sdk` directory. +In a new terminal window, navigate to the SDK directory. ```bash -cd bindings/javascript/sdk +cd quickstarts/bindings/javascript/sdk ``` Install the dependencies: @@ -266,11 +284,18 @@ npm install Run the `javascript-quickstart-binding-sdk` service alongside a Dapr sidecar. ```bash -dapr run --app-id javascript-quickstart-binding-sdk --app-port 3500 --dapr-http-port 5051 node batch.js --components-path ../../components +dapr run --app-id javascript-quickstart-binding-sdk --app-port 3500 --dapr-http-port 5051 --components-path ../../components node batch.js ``` -The `javascript-quickstart-binding-sdk` uses the PostgreSQL Output Binding defined in the [`bindings.yaml`]({{< ref "#bindingsyaml-component-file" >}}) component to insert the `OrderId`, `Customer` and `Price` records into the `orders` table. This code is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). -```js +The code inside the `process_batch` function is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks like a route called via HTTP POST in your Flask application by the Dapr sidecar. + +```javascript + +``` + +The `javascript-quickstart-binding-sdk` service uses the PostgreSQL output binding defined in the [`bindings.yaml`]({{< ref "#bindingsyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. + +```javascript async function processBatch(){ const loc = '../../orders.json'; fs.readFile(loc, 'utf8', (err, data) => { @@ -287,43 +312,67 @@ async function processBatch(){ } ``` -### Step 5: View the Output Binding log +### Step 4: View the output of the job -Notice, as specified above, the code invokes the Output Binding with the `OrderId`, `Customer` and `Price` as a payload. +Notice, as specified above, the code invokes the Output Binding with the `OrderId`, `Customer`, and `Price` as a payload. + +Your output binding's `print` statement output: -Output Binding `console.log` statement output: ``` -== APP == [Dapr-JS] Server Started -== APP == { "sql": "insert into orders (orderid, customer, price) values (1, 'John Smith', 100.32);" } -== APP == { "sql": "insert into orders (orderid, customer, price) values (2, 'Jane Bond', 15.4);" } -== APP == { "sql": "insert into orders (orderid, customer, price) values (3, 'Tony James', 35.56);" } -== APP == Finished processing batch +== APP == Processing batch.. +== APP == insert into orders (orderid, customer, price) values(1, 'John Smith', 100.32) +== APP == insert into orders (orderid, customer, price) values(2, 'Jane Bond', 15.4) +== APP == insert into orders (orderid, customer, price) values(3, 'Tony James', 35.56) ``` -### Step 6: Process the `orders.json` file on a schedule +In a new terminal, verify the same data has been inserted into the database. Navigate to the `bindings/db` directory. -The `javascript-quickstart-binding-sdk` uses the Cron Input Binding defined in the [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) component to process a json file containing order information. - -```js -const server = new DaprServer(serverHost, serverPort, daprHost, daprPort); - -async function start() { - await server.binding.receive(cronBindingName,processBatch); - await server.start(); -} +```bash +cd quickstarts/bindings/db ``` -#### `cron.yaml` component file +Run the following to start the interactive Postgres CLI: -When you execute the `dapr run` command and specify the location of the component file, the Dapr sidecar initiates the Cron [Binding building block]({{< ref bindings >}}) and calls the binding endpoint (`batch`) every 10 seconds. +```bash +docker exec -i -t postgres psql --username postgres -p 5432 -h localhost --no-password +``` -The Cron `cron.yaml` file included for this Quickstart contains the following: +At the `admin=#` prompt, change to the `orders` table: + +```bash +\c orders; +``` + +At the `orders=#` prompt, select all rows: + +```bash +select * from orders; +``` + +The output should look like this: + +``` + orderid | customer | price +---------+------------+-------- + 1 | John Smith | 100.32 + 2 | Jane Bond | 15.4 + 3 | Tony James | 35.56 +``` + +#### `components\binding-cron.yaml` component file + +When you execute the `dapr run` command and specify the component path, the Dapr sidecar: + +- Initiates the Cron [Binding building block]({{< ref bindings >}}) +- Calls the binding endpoint (`batch`) every 10 seconds + +The Cron `binding-cron.yaml` file included for this Quickstart contains the following: ```yaml apiVersion: dapr.io/v1alpha1 kind: Component metadata: - name: batch + name: cron namespace: quickstarts spec: type: bindings.cron @@ -333,28 +382,31 @@ spec: value: "@every 10s" # valid cron schedule ``` -**Note:** The `metadata` section of `cron.yaml` contains a [cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding will be invoked. +**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding will be invoked. -#### `bindings.yaml` component file +#### `component\bindings-postgres.yaml` component file -When you execute the `dapr run` command and specify the location of the component file, the Dapr sidecar initiates the PostgreSQL [Binding building block](/reference/components-reference/supported-bindings/postgres/) and connects to PostgreSQL using the settings specified in the `bindings.yaml` file. +When you execute the `dapr run` command and specify the component path, the Dapr sidecar: -With the `bindings.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. +- Initiates the PostgreSQL [Binding building block]({{< ref /reference/components-reference/supported-bindings/postgres.md >}}) +- Connects to PostgreSQL using the settings specified in the `bindings-postgres.yaml` file -The PostgreSQL `bindings.yaml` file included for this Quickstart contains the following: +With the `bindings-postgres.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. + +The PostgreSQL `bindings-postgres.yaml` file included for this Quickstart contains the following: ```yaml apiVersion: dapr.io/v1alpha1 kind: Component metadata: - name: SqlDB + name: sqldb namespace: quickstarts spec: type: bindings.postgres version: v1 metadata: - name: url # Required - value: "user=admin password=admin host=localhost port=5432 dbname=orders pool_min_conns=1 pool_max_conns=10" + value: "user=postgres password=docker host=localhost port=5432 dbname=orders pool_min_conns=1 pool_max_conns=10" ``` In the YAML file: @@ -378,60 +430,46 @@ For this example, you will need: ### Step 1: Set up the environment Clone the [sample we've provided in our Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/bindings). + ```bash git clone https://github.com/dapr/quickstarts.git ``` -### Step 2: Run PostgreSQL Docker Container Locally +### Step 2: Run PostgreSQL Docker container locally -In order to run the PostgreSQL bindings quickstart locally, you will run the [PostgreSQL instance](https://www.postgresql.org/) in a docker container on your machine. +You will run the [PostgreSQL instance](https://www.postgresql.org/) locally in a Docker container on your machine. The Quickstart sample includes a Docker Compose file to locally customize, build, run, and initialize the `postgres` container with a default `orders` table. -To run the container locally, run: +In a terminal window, from the root of the Quickstarts clone directory, navigate to the `bindings\db` directory. ```bash -docker run --name sql_db -p 5432:5432 -e POSTGRES_PASSWORD=admin -e POSTGRES_USER=admin -d postgres +cd quickstarts/bindings/db ``` -To see the container running locally, run: +Run the following command to set up the container: + +```bash +docker compose up +``` + +Verify that the container is running locally. + ```bash docker ps ``` -The output should be similar to this: +The output should include: + ```bash CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 55305d1d378b postgres "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:5432->5432/tcp sql_db ``` -### Step 3: Setup the database schema +### Step 3: Schedule a Cron job and write to the database -Connect to the local PostgreSQL instance. -```bash -docker exec -i -t sql_db psql --username admin -p 5432 -h localhost --no-password -``` -This will launch the PostgreSQL cli. -```bash -psql (14.2 (Debian 14.2-1.pgdg110+1)) -Type "help" for help. - -admin=# -``` -Create a new `orders` database. -```bash -create database orders; -``` -Connect to the new database and create the `orders` table. -```bash -\c orders; -create table orders ( orderid int, customer text, price float ); select * from orders; -``` - -### Step 4: Schedule a Cron job and write to the database - -In a terminal window, navigate to the `sdk` directory. +In a new terminal window, navigate to the SDK directory. ```bash -cd bindings/csharp/sdk +cd quickstarts/bindings/csharp/sdk ``` Install the dependencies: @@ -446,57 +484,89 @@ Run the `csharp-quickstart-binding-sdk` service alongside a Dapr sidecar. ```bash dapr run --app-id csharp-quickstart-binding-sdk --app-port 7001 --components-path ../../components -- dotnet run --project batch.csproj ``` -The `csharp-quickstart-binding-sdk` uses the PostgreSQL Output Binding defined in the [`bindings.yaml`]({{< ref "#bindingsyaml-component-file" >}}) component to insert the `OrderId`, `Customer` and `Price` records into the `orders` table. This code is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). -```cs -foreach( Order ord in ordersArr.orders){ - var sqlText = $"insert into orders (orderid, customer, price) values ({ord.OrderId}, '{ord.Customer}', {ord.Price});"; - var command = new Dictionary(){ - {"sql", - sqlText} - }; - await client.InvokeBindingAsync(sqlBindingName, "exec", command,command); - Console.WriteLine(sqlText); -} +The code inside the `process_batch` function is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks like a route called via HTTP POST in your Flask application by the Dapr sidecar. + +```csharp +Console.WriteLine("Processing batch.."); +string jsonFile = File.ReadAllText("../../orders.json"); +var ordersArray = JsonSerializer.Deserialize(jsonFile); ``` -### Step 5: View the Output Binding log +The `csharp-quickstart-binding-sdk` service uses the PostgreSQL output binding defined in the [`bindings.yaml`]({{< ref "#bindingsyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. -Notice, as specified above, the code invokes the Output Binding with the `OrderId`, `Customer` and `Price` as a payload. - -Output Binding `Console.WriteLine` statement output: -``` -== APP == insert into orders (orderid, customer, price) values (1, 'John Smith', 100.32); -== APP == insert into orders (orderid, customer, price) values (2, 'Jane Bond', 15.4); -== APP == insert into orders (orderid, customer, price) values (3, 'Tony James', 35.56); +```csharp +using var client = new DaprClientBuilder().Build(); + foreach(Order ord in ordersArray?.orders ?? new Order[] {}){ + var sqlText = $"insert into orders (orderid, customer, price) values ({ord.OrderId}, '{ord.Customer}', {ord.Price});"; + var command = new Dictionary(){ + {"sql", + sqlText} + }; + Console.WriteLine(sqlText); ``` -### Step 6: Process the `orders.json` file on a schedule +### Step 4: View the output of the job -The `csharp-quickstart-binding-sdk` uses the Cron Input Binding defined in the [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) component to process a json file containing order information. +Notice, as specified above, the code invokes the Output Binding with the `OrderId`, `Customer`, and `Price` as a payload. -```cs -app.MapPost(cronBindingName, async () => { +Your output binding's `print` statement output: - string text = File.ReadAllText("../../orders.json"); - var ordersArr = JsonSerializer.Deserialize(text); - using var client = new DaprClientBuilder().Build(); - ... - } -}); +``` +== APP == Processing batch.. +== APP == insert into orders (orderid, customer, price) values(1, 'John Smith', 100.32) +== APP == insert into orders (orderid, customer, price) values(2, 'Jane Bond', 15.4) +== APP == insert into orders (orderid, customer, price) values(3, 'Tony James', 35.56) ``` -#### `cron.yaml` component file +In a new terminal, verify the same data has been inserted into the database. Navigate to the `bindings/db` directory. -When you execute the `dapr run` command and specify the location of the component file, the Dapr sidecar initiates the Cron [Binding building block]({{< ref bindings >}}) and calls the binding endpoint (`batch`) every 10 seconds. +```bash +cd quickstarts/bindings/db +``` -The Cron `cron.yaml` file included for this Quickstart contains the following: +Run the following to start the interactive Postgres CLI: + +```bash +docker exec -i -t postgres psql --username postgres -p 5432 -h localhost --no-password +``` + +At the `admin=#` prompt, change to the `orders` table: + +```bash +\c orders; +``` + +At the `orders=#` prompt, select all rows: + +```bash +select * from orders; +``` + +The output should look like this: + +``` + orderid | customer | price +---------+------------+-------- + 1 | John Smith | 100.32 + 2 | Jane Bond | 15.4 + 3 | Tony James | 35.56 +``` + +#### `components\binding-cron.yaml` component file + +When you execute the `dapr run` command and specify the component path, the Dapr sidecar: + +- Initiates the Cron [Binding building block]({{< ref bindings >}}) +- Calls the binding endpoint (`batch`) every 10 seconds + +The Cron `binding-cron.yaml` file included for this Quickstart contains the following: ```yaml apiVersion: dapr.io/v1alpha1 kind: Component metadata: - name: batch + name: cron namespace: quickstarts spec: type: bindings.cron @@ -506,28 +576,31 @@ spec: value: "@every 10s" # valid cron schedule ``` -**Note:** The `metadata` section of `cron.yaml` contains a [cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding will be invoked. +**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding will be invoked. -#### `bindings.yaml` component file +#### `component\bindings-postgres.yaml` component file -When you execute the `dapr run` command and specify the location of the component file, the Dapr sidecar initiates the PostgreSQL [Binding building block](/reference/components-reference/supported-bindings/postgres/) and connects to PostgreSQL using the settings specified in the `bindings.yaml` file. +When you execute the `dapr run` command and specify the component path, the Dapr sidecar: -With the `bindings.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. +- Initiates the PostgreSQL [Binding building block]({{< ref /reference/components-reference/supported-bindings/postgres.md >}}) +- Connects to PostgreSQL using the settings specified in the `bindings-postgres.yaml` file -The PostgreSQL `bindings.yaml` file included for this Quickstart contains the following: +With the `bindings-postgres.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. + +The PostgreSQL `bindings-postgres.yaml` file included for this Quickstart contains the following: ```yaml apiVersion: dapr.io/v1alpha1 kind: Component metadata: - name: SqlDB + name: sqldb namespace: quickstarts spec: type: bindings.postgres version: v1 metadata: - name: url # Required - value: "user=admin password=admin host=localhost port=5432 dbname=orders pool_min_conns=1 pool_max_conns=10" + value: "user=postgres password=docker host=localhost port=5432 dbname=orders pool_min_conns=1 pool_max_conns=10" ``` In the YAML file: @@ -551,59 +624,46 @@ For this example, you will need: ### Step 1: Set up the environment Clone the [sample we've provided in our Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/bindings). + ```bash git clone https://github.com/dapr/quickstarts.git ``` -### Step 2: Run PostgreSQL Docker Container Locally -In order to run the PostgreSQL bindings quickstart locally, you will run the [PostgreSQL instance](https://www.postgresql.org/) in a docker container on your machine. +### Step 2: Run PostgreSQL Docker container locally -To run the container locally, run: +You will run the [PostgreSQL instance](https://www.postgresql.org/) locally in a Docker container on your machine. The Quickstart sample includes a Docker Compose file to locally customize, build, run, and initialize the `postgres` container with a default `orders` table. + +In a terminal window, from the root of the Quickstarts clone directory, navigate to the `bindings\db` directory. ```bash -docker run --name sql_db -p 5432:5432 -e POSTGRES_PASSWORD=admin -e POSTGRES_USER=admin -d postgres +cd quickstarts/bindings/db ``` -To see the container running locally, run: +Run the following command to set up the container: + +```bash +docker compose up +``` + +Verify that the container is running locally. + ```bash docker ps ``` -The output should be similar to this: +The output should include: + ```bash CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 55305d1d378b postgres "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:5432->5432/tcp sql_db ``` -### Step 3: Setup the database schema +### Step 3: Schedule a Cron job and write to the database -Connect to the local PostgreSQL instance. -```bash -docker exec -i -t sql_db psql --username admin -p 5432 -h localhost --no-password -``` -This will launch the PostgreSQL cli. -```bash -psql (14.2 (Debian 14.2-1.pgdg110+1)) -Type "help" for help. - -admin=# -``` -Create a new `orders` database. -```bash -create database orders; -``` -Connect to the new database and create the `orders` table. -```bash -\c orders; -create table orders ( orderid int, customer text, price float ); select * from orders; -``` - -### Step 4: Schedule a Cron job and write to the database - -In a terminal window, navigate to the `sdk` directory. +In a new terminal window, navigate to the SDK directory. ```bash -cd bindings/go/sdk +cd quickstarts/bindings/go/sdk ``` Install the dependencies: @@ -612,102 +672,96 @@ Install the dependencies: go build batch.go ``` -Run the `go-input-binding-sdk` service alongside a Dapr sidecar. +Run the `go-quickstart-binding-sdk` service alongside a Dapr sidecar. ```bash -dapr run --app-id go-input-binding-sdk --app-port 6002 --dapr-http-port 6003 --dapr-grpc-port 60002 go run batch.go --components-path ../../components -``` -The `go-input-binding-sdk` uses the PostgreSQL Output Binding defined in the [`bindings.yaml`]({{< ref "#bindingsyaml-component-file" >}}) component to insert the `OrderId`, `Customer` and `Price` records into the `orders` table. This code is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). - -```go -func sqlBindings(order Order) (err error) { - - bindingName := "SqlDB" - - client, err := dapr.NewClient() - if err != nil { - return err - } - - ctx := context.Background() - - sqlCmd := fmt.Sprintf("insert into orders (orderid, customer, price) values (%d, '%s', %s);", order.OrderId, order.Customer, strconv.FormatFloat(order.Price, 'f', 2, 64)) - fmt.Println(sqlCmd) - in := &dapr.InvokeBindingRequest{ - Name: bindingName, - Operation: "exec", - Data: []byte(""), - Metadata: map[string]string{"sql": sqlCmd}, - } - err = client.InvokeOutputBinding(ctx, in) - if err != nil { - return err - } - return nil -} +dapr run --app-id go-input-binding-sdk --app-port 6002 --dapr-http-port 6003 --dapr-grpc-port 60002 --components-path ../../components go run batch.go ``` -### Step 5: View the Output Binding log - -Notice, as specified above, the code invokes the Output Binding with the `OrderId`, `Customer` and `Price` as a payload. - -Output Binding `console.log` statement output: -``` -== APP == The File is opened successfully... -== APP == dapr client initializing for: 127.0.0.1:60002 -== APP == insert into orders (orderid, customer, price) values (1, 'John Smith', 100.32); -== APP == insert into orders (orderid, customer, price) values (2, 'Jane Bond', 15.40); -== APP == insert into orders (orderid, customer, price) values (3, 'Tony James', 35.56); -== APP == Finished processing batch -``` - -### Step 6: Process the `orders.json` file on a schedule - -The `go-input-binding-sdk` uses the Cron Input Binding defined in the [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) component to process a json file containing order information. +The code inside the `process_batch` function is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks like a route called via HTTP POST in your Flask application by the Dapr sidecar. ```go func processCron(w http.ResponseWriter, r *http.Request) { - fileContent, err := os.Open("../../orders.json") - if err != nil { - log.Fatal(err) - return - } - - fmt.Println("The File is opened successfully...") - - defer fileContent.Close() - - byteResult, _ := ioutil.ReadAll(fileContent) - - var orders Orders - - json.Unmarshal(byteResult, &orders) - - for i := 0; i < len(orders.Orders); i++ { - err := sqlBindings(orders.Orders[i]) - if err != nil { - log.Fatal(err) - os.Exit(1) - } - } - fmt.Println("Finished processing batch") - os.Exit(0) } - ``` -#### `cron.yaml` component file +The `go-quickstart-binding-sdk` service uses the PostgreSQL output binding defined in the [`bindings.yaml`]({{< ref "#bindingsyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. -When you execute the `dapr run` command and specify the location of the component file, the Dapr sidecar initiates the Cron [Binding building block]({{< ref bindings >}}) and calls the binding endpoint (`batch`) every 10 seconds. +```go +client, err := dapr.NewClient() + // ... +sqlCmd := fmt.Sprintf("insert into orders (orderid, customer, price) values (%d, '%s', %s);", order.OrderId, order.Customer, strconv.FormatFloat(order.Price, 'f', 2, 64)) +fmt.Println(sqlCmd) +in := &dapr.InvokeBindingRequest{ + Name: bindingName, + Operation: "exec", + Data: []byte(""), + Metadata: map[string]string{"sql": sqlCmd}, +} +``` -The Cron `cron.yaml` file included for this Quickstart contains the following: +### Step 4: View the output of the job + +Notice, as specified above, the code invokes the Output Binding with the `OrderId`, `Customer`, and `Price` as a payload. + +Your output binding's `print` statement output: + +``` +== APP == Processing batch.. +== APP == insert into orders (orderid, customer, price) values(1, 'John Smith', 100.32) +== APP == insert into orders (orderid, customer, price) values(2, 'Jane Bond', 15.4) +== APP == insert into orders (orderid, customer, price) values(3, 'Tony James', 35.56) +``` + +In a new terminal, verify the same data has been inserted into the database. Navigate to the `bindings/db` directory. + +```bash +cd quickstarts/bindings/db +``` + +Run the following to start the interactive Postgres CLI: + +```bash +docker exec -i -t postgres psql --username postgres -p 5432 -h localhost --no-password +``` + +At the `admin=#` prompt, change to the `orders` table: + +```bash +\c orders; +``` + +At the `orders=#` prompt, select all rows: + +```bash +select * from orders; +``` + +The output should look like this: + +``` + orderid | customer | price +---------+------------+-------- + 1 | John Smith | 100.32 + 2 | Jane Bond | 15.4 + 3 | Tony James | 35.56 +``` + +#### `components\binding-cron.yaml` component file + +When you execute the `dapr run` command and specify the component path, the Dapr sidecar: + +- Initiates the Cron [Binding building block]({{< ref bindings >}}) +- Calls the binding endpoint (`batch`) every 10 seconds + +The Cron `binding-cron.yaml` file included for this Quickstart contains the following: ```yaml apiVersion: dapr.io/v1alpha1 kind: Component metadata: - name: batch + name: cron namespace: quickstarts spec: type: bindings.cron @@ -717,28 +771,31 @@ spec: value: "@every 10s" # valid cron schedule ``` -**Note:** The `metadata` section of `cron.yaml` contains a [cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding will be invoked. +**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding will be invoked. -#### `bindings.yaml` component file +#### `component\bindings-postgres.yaml` component file -When you execute the `dapr run` command and specify the location of the component file, the Dapr sidecar initiates the PostgreSQL [Binding building block](/reference/components-reference/supported-bindings/postgres/) and connects to PostgreSQL using the settings specified in the `bindings.yaml` file. +When you execute the `dapr run` command and specify the component path, the Dapr sidecar: -With the `bindings.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. +- Initiates the PostgreSQL [Binding building block]({{< ref /reference/components-reference/supported-bindings/postgres.md >}}) +- Connects to PostgreSQL using the settings specified in the `bindings-postgres.yaml` file -The PostgreSQL `bindings.yaml` file included for this Quickstart contains the following: +With the `bindings-postgres.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. + +The PostgreSQL `bindings-postgres.yaml` file included for this Quickstart contains the following: ```yaml apiVersion: dapr.io/v1alpha1 kind: Component metadata: - name: SqlDB + name: sqldb namespace: quickstarts spec: type: bindings.postgres version: v1 metadata: - name: url # Required - value: "user=admin password=admin host=localhost port=5432 dbname=orders pool_min_conns=1 pool_max_conns=10" + value: "user=postgres password=docker host=localhost port=5432 dbname=orders pool_min_conns=1 pool_max_conns=10" ``` In the YAML file: @@ -751,6 +808,7 @@ In the YAML file: {{< /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.gg/22ZtJrNe). diff --git a/daprdocs/static/images/bindings-quickstart/bindings-quickstart.png b/daprdocs/static/images/bindings-quickstart/bindings-quickstart.png new file mode 100644 index 0000000000000000000000000000000000000000..842ad2387991aa6cd7123b69ab0260e3484ee7de GIT binary patch literal 23076 zcmaI8Wn7fq_dPt6ASfLQC^dkDqI5_|cMl!XDIq0|NQ@xeEe%7Dbc1y2NT*0hgLLyh z+`sSh_IbevX09{WoOAZR_St)_wfU^7Eb|bT5*Gr2Jd~4_REIz?UqB#eLOAH)oeT$U zKky69MO{W5Qa(bx0bXEQy-|7tfmB7|U728k*Y}-dbzLA3{O@-^XuXa_<`9T(gPi0W z%@0O9^Y=e!j?ef0izXzDevURxL06w6sS6W(6HHi279Kb=S!)gZF^NS+dJIE+rIo@% z3qlWjuAgsPCg~(`pH)Fsl_-HwZCaCoECRN3m(c^&rf zr1Hosl_}GrLC(a$7sqSRN!}n@4Xwv$YhFj^6*4hv|AIjv^H6%F&Jh+{guoD zDX*CM+VkI^Zm%hmzGylInaFrIX#xzfXR8Wi`n#nH|6 zC5Lfq`Zhjo(0~Md8C|zGvfIF}!a*FxEnFkb`Vmvi`o|!WB1cy8{9EpiEN4i2p$2avT1PnC|0?i&9odV6D~SPv96H-9ErPv57OyufQO}2VS}- zQl$5r5bV2P5IWK-t5KydCimn%opeoJo@Im`_g^L`lgKLI^mK$}Qi(7uS+QOjuZ9LT;P__ zM_#)BBA%%;R#he=5s>>iuY=-^pOlnt%l@gIoeRR0r9MIuqp3kyU5@2>U`i4VB%$gK<0WpX-`$;H;{x(S} z8iobO2qN^?R4JY)z4~%8c65PB+`h1G!N`;YH{PzFszN|`YqW!-a~Se1{`tF=M*rZW z1MaSxloky+k>Fs9A(HZ`yv*rApijYZ>6*eLuf%cg8=Nc2QYI{tRlNY_vJW&Ohtogp z{`IFDf!Pw%r_=EoBfyDOp8(|B3iwkw|ABXmAOVz#i?!Rha})K?-P zM73@7L05`6pV{4-Cs=GSiD`4zEq)FjyvWYQ35R$7g-8bA(j9o5C7Cti#w5h5mkEHS z(FZRCcmDlt7${9dj;HOzB$gacEm)we$Q;xam|8rZ%2Pi51?-cFL{ukP)@SDX6jC~* z&C7>q;zjg9@lS4ozgL+m?8L>U@gV*iM<>P6DI`LpeVuV)5;qD<){9i)=mE1WYfyjwKh3 zKd-~~d9;#X`p%i$Xj!5md1%lyru zGk>X>)q=(u4$g*RD)Dbh_ejKXK6~@1$H8cqn4q%e_Wu|-oJCw_Wr(z**8d#Jhzn>E ziQ^NB6W`~fd(&ykMq~JS|9qA|tkSCszZI`b_&!~%7&H`IPh5$%T=l-&3}STslPRLb z#o*_;U_$nPyx$nm2el)BTMeT$7~{rPn4oYC`(ZPUW-a0()D}E+g$pz%FbD@8Q+DpCv7CrW1zA(ctp!7B$WGjc|`OsmU>1)Ta=xODs@Nm}F7N6jKe8PLlLZsfk@$ z^7cWCi~v|yfCWTNhV%_ih5=hXg&Jnn$LH*({*U2$V44ABgBUsRXMu!*4es(4ia9tr zU&>fZO+7u~;&)e>*{R^T;0uc!cH%Q7i6ja1)jtrY4N6M_>tJ7Xybr`-2%`;x)5FPY zGxudmpEDDMfkokv4nCj{0XIcxGq2_-gU^xbD`K*`C#J|s#$-!`BE4w&Gqn<=!pS$# zz7D|Yap-bz=)V||2a@Bpl!76)-~9NsAAxG|_JA?{HxZoddu}DhPRfSDkRX~C_8`e>FI}PtdRH1XDRu=M zY;dFX_63QuUvXYX*2SS8Uz!cVRX-0P<4bR`ArRQfa^`oB`RlcM=Ms_YBWyz~$bJCG zSj76$`ThR%(hv-19`+l0JkPosN`0;$c8mdmP=NFSA}*Z+XSKg{za1;K+iUbb|MK`; z$emg>0RmyW%eClSnh#!0r19;goE^y!%dQR2>NKBP8R9{l?lLk$P6w4!gEqfOGc)Z4 zx5>0yuZ?hHKLLat8toDhNVsrPNP68m#u2c^h^N;hzv4tt-yzZaaC!(N=*wvM+ufOd zPX@@>|3*G8bdfTEDNJbZVngn7HJm4-*w!rlV2VX|$q}u&&n}rN8~O(|R)YqEE0k)Okboa16*!Qyi2nvspFWo2*T#gf{&&~MG;e~!&(Q<0 z?uJGGYtaq@gUJ57N95kK96Sg_PZDfO$YmHL;P(F}S^@2Bpoi@L-*zk?8pOnt);2@F z{-i~R5DHR%#e(=TghB4-6%|>7g?iBr;o{-(Im{Jd2Lw4^)xY@AX|rWQ|1gqU$cr|e zemWZ6If|U9vd)(5sL~1;OhdFLlO=S4wol8TwGkt%IQTV0bNd= zlNn(CT`DNAqLA(^%a!cVr?K~BQZs&pU`~4C7)#(nnR0N5lk8>3c$wb#EzUH!{9S1A z&ad=2e-9%O$@0HxU~RtKZ9+hxaFW*3Fidi(u&^-8k#v?Fn4Vs$Es~RyQ~JxJ4uV6i zt;q`QU;@!ARkBWK>_e7l95}t$&~&|X?$PT;_Z`Za@}3l{%;`3Nf0i$gxunN~qMB8~ zRH=CF&w52~)U?qOER5p|Zk|3C(9!M=CK1_VBkpUUZ)j+EBIsJbQ#+ftT;kPkx;0V8 zWjUlOI;5bgmhdL}@4yk`_=6{cn%cp-CMHWcQsFDB;;n6(sgyQOdDCiT24|8;IxLWf zV8R7*Wug)@W&HeFpW??H9UWN=CT8$Eo6glcH?rCbx@~Hzs;U|oP*=TBMxQy_u>Fz+{+ zGf~mo5Gn`NT(p24;F+|U!x=YIV6y8US@lnU>T}klmG6{>E_I%w>D@@h{LGap5x>2; zW(>+JEG&7GZ#A09rd6uCx;mKTvVa3gqYr~56nzs9jy)g?CjiooyQwtUiY{79SHDaym~d+3@@a|aaaZiJjqD0ZsV;9yz-z))r-%E$O%2BAEI^dA!`G36ttk2%bS3sW_O5mKbcg zg>ejquUt_ygBe$m_ttlehO?krU{e?6C99uDj(C`VW(yFON5) z9l&-W)$U(Fc7OLZTUc7AK3-^aE3x0Uz$?7xJ5z0=k@UiFs7Y1De?2>NEH})DX%l=K zrn3`VG^=dr+-=g(%FE0)Jw2V82Ztk-*U|f*g|_J7X`OQUte7?N1W!eP3}9I)8ogJ#ud0oH20xD2CSv!Vzk(BWh zxhh#A4$DFM2;ovP+T;9j?O&(GEOc-z? z$r!@u7xCOKYlWmSF)^=P*MIc!P2kX-E9a9$CneRnZm7G&uIEOHAaJ!fE%o$fI)m{n z%+DvO+pqf=qKb&F_)I!6Q{bKre>1(6?{$M%P;A?LcD?7n2too673UKei$1?-(syhc zpGx1$lLO1uje{Q8>e;{L;R&_tFNFi&LkYCa{7!fElM=q;qlx8i)e?I8k)VRj!)Qwq(ctWTuQ~-JVvjN$23rOd`cf} zxmTXw?s~LoFnnO%6Q3a&Z%k#<%M`I1q2>upe(j0Gr9(YHglPA~zyG?EHX5SYXJ4{6 zIAcmdL6Js^2_?;uO|YMm`#djev8fqO3Trs5>JyljEQJy1SnsEd~|aovxSU z-}j~R*qQr0*1bt^9_vGDVqUOm11~qHU;DcMZB#`6UKx*(>(+$Qn#OQXky@^~e$nRb z#bg^I&;xlMUpSbSP&i1XtzANTFrjIJ%9FD_WYHhq_*Gc)D*vq)*UjPiw8+)|cf|gT zT}1>H-^dr6HQXC(RB6o%M#k}S4V5H9OA&$}2Y*dl*Iqm}p;rnk)k1aZUQf`Co8g89YKI5`@)?0p_7u#e312dIBQcRwTQB) z)j+N4JIS)}B8t-m?}}r?2bA2hWJANaFnyN6T6-Q?1bx~&!-KTbQ7ua6n&PLN=5YJG zCsEc+Iqfu5lNDq6d3lFThB*r4du`VT)pDovZol%^h}+c@DGNyy5{I&Ko*K5TO@4w6 zX{@Md>)Kzq*37a{kgs?5!}@Rj%xN3HRB70l8R2Zz+zj1e&@3$LMYoYi*V<2WXp|%C ze3DpdkcMtkq1nN$YSh>C@*Of-E+tD;GeUrRx1Twyn)j1>>uRF@QGmY>Z(c>~1%j2o zW{OiA<@p2SmE-xr>fNa)5|t$4TGU7W#%<9I!SUkN&=qkRuTIzn`kU2gquW-Z04W8<-__OWBHfQ{g^Qcb)J#8-77B)l zw|?h%r@sDW1{DPyN@=WTF2s4inqG<~v7)vS1>XStgXm%XAvJ$#)nwL-4|BR6%4lTR z7w-&^!*AhuGFIJS#FXGh)8h6{tLc8!Li15VgMRCkY;*Seo2@7?u}b=Y=O75vPg2FNcd>;?lQQ(}ko|(MAqE zNVU^=JHzHbvg+hZp}dp4fi76%{ihR;V~p|kgQINlMr~v56bLip`BMze$`=BrL&>iS zI+7v+U4uI3KPC?4Htu=x-yJKmZcmDD|VTH%Tzkhy`iK^iGvnFciz#fgn+1W}SA z-hcYQ91moHF62dgY%834Yag1?fnMFs@o$}f zKO_i>ztIGD5j=h)EG6q=GGa^|t3$kB$p_ZAHk4wPv$H+@?fU$DfZD0}$gyOM^@oMUa$k6vhZQ=q%&dqWKM`_|_fO+yQW%XGMO&wabd=4^Ps_bWjW3mp}jc#N;6h0B;tept^&=io$k_dTvFd+&RpQf zPazwjaj`coV#XEr`wu-3gP8iuVGZt;R~v}DJZ74PeuKZ-1^&I)aTXWg;Phl$U7gEB z(sOYL*9+gnsJ`MC8N4!R{P53|BfO;{q(VSK(6mWoY?_k3QOHTq z1Ap(iL#^Xtxx!N2JAIt;`X`Sw1l>3%lOv0-$zuKuuvHXw?k{~W>%CzSe!@(-fi{>T zE8dfIwp8tHENxU}8Z6I%s^d-ym7|u7c{`NKqd*1{g5}1japwMBOVRm{7}%QmE7&fC z*$5)_#MIsSChuu9R)rn6L_1P>I#z8xMRP{Rkx3>_QS(~spW-*i$YP@=_p%qT6b3`uA3aO{k1#9;sFNT-WZ8pRBItNk0^fi9T#MUMq^R z;B{zojO97;Id91DlRatBhB9`aCTiERGesnGb!YUscU+CxDlffk(nz^a{W9BEs_tZOu|k1tsH#F)R1~|H`td5|Ymv)sE<;?R!9a*sKwo@~S2)xbnusEoqV~btE zCQ~*y;gK;%#Itiu7OK$H*>x&#v_RA7ZDvZB!!Z@d)wnGNNDbddJ8BrZXtm16X^v|z zk9Em@vU9J{#X4nMUg?i>>+jfZa=9L6;$Ms9u@uV2bRIU{8xo<`tu52X(Z%9_CrnHH zfV_?0bBgCLM~blx5t$)J{oKYjk(6oshSkRM0Y*#IQuw!?4Rv*tA;Hb?PWdAhsQ0>h z@F4OS&9c)-n;yTvfxeS{2bEd0kU*)Kml3lQ$f~gHNEvZ)yj2o7Z9>1&pdz~C6P>x= z@SRswba7^obj>=wq`Xm{4Be~yckCx_tcgSorkgPhmEwcdB;#^iShl+{-uX~j);FH* z;IQe4<@lHRh7Wff1=WatL?JkzC6qIy`QqP1PrYqXNU%R%VT&vMLus7x;X+NP))ghk zwHREA&Y7zCqw#Grhnmr#4VJToA7$(9&1K6K`!jvpU%~oF^UthMoE+KqA$qpJDMos{ zeD-$=NiT$#zWUkUEYlow1cSVd)vmiP$eB+f4hc=81*oSi#1s^QwYwl+Y@zHo5QPXf9;95I2 zn?#_*tLI!fdDA2`Tk8Y;sT7P1=-_8?{;Ki?QW4X=U)Qq4wP+on9NYvoL+H6sfAd3C|edzdJesGL{ zHV2f8X(!4nn~?LeBJY$vE87SCKo4cA(1h6B>Ga|c*zE74y1y<1o0ctRGHf+)^C#P& z?Dv@Y`f=e^Nx|1v%4|P3vVuWqR_6ITZKj;32|x4fR(!v&oXD7bmbSdH;2pc_Gq+G> zvTjMK@cC>x``j+a$2arDtdDz`ek@mp0Jh&{poqGBZ2B+s8L&{^GyY7I5lc)qgJ_n-vH{RbG`@gS_A zj#L~;U-U4*C;8xHwPr;kE>nr{^rf5_s%+1zW3_IP&jyr~jjSvi!GCZ5xSGtJF8b*P z_Ey@BwE2IiHBSKbcOoJ2dM076^{9iPy!-&aaOI-)=C}t*Um0%e%vXil-HhWm0_ zf-dqUrFh6jxh6Whtm+50L39!!?E1As7aAp{d*xfj_NJLW2Xe5Dt}pDsrWr4OvQd#v z4-|!(3$ljxU0q!+-fA(x1B}!zN)c8pjxt)dkAMBGm=sqsu1P?)A6hZTRZd0`?oH|_hJo!7?kUjQAEa` zAqA#PX$;Q%Fag+4oKpcGC!V+Mki*%}Ae;ZRR<9y8Lu=D8bjldsf!P~@KK_-&W-Xm* zef0Al>dzoIESF`a=HTF9=zxTn^ZUWX(3gI4*)^_ej_kfLS}Mq)dtP_a^9WZWgNiTr zIbO7G+qyNv`9Hi})Hc4F8T0{9BuEtPA3o)@1c*WC96wSwT*D1Ui%)am7M}Lo=jm6n zAHGuN*Rh%DM-iphn!4B)5z%A@UYh0l4|P>CQqgUEUY7}>(vswgl@qSEyo7aiNy-?C zczzaZko{njFI=1?cR!>ZN8JZOw?NfL#pHjE% z9!E4-df6K!7+c9IiV*Bp6K&JtsCbrDIj!8l_@;Y9W+{TKcVST5@j6)Ba_#1FPkWVb z;e!NOklx!;yL?)v-=y;Vq%r1mFAa1zYRPE&qtkFj5F=n9!I)!8TDKCT!h1O zY=fSbzqB2D2HT5=lG*&cqhqC`17{Z+str(%s>?;jU-D2xpD25sQoja~TnFIsL`EYO zH3~}at=6Pl!tRYr9ON{D%9(bk&sOB2r=4ZbN&|vL`;&MC!%(k*Wz z?WJR3eZ5ZYuL**WeLIClzWyZ&k$7i_&e(H}AvGP4u*Y*bTI^zX`==d_fRyZNX(BYO z?g3NSSh8r99Mp7<~USd zWy~wpqvI*?q;O!~y4VaWBzUtqJnKAf9(0)+`X>5!w(>H$)2+PQ08O#+$9X2L_@Po3^-Dhbn+8_ z713)~oNpDQ5|$a_ucK9Y^~xJVbaHT;}`CD1vaeR&2 z@O^slA6FxJae!UMKu*JGiINqFQZedG!&ZXslcNq_ym)bflo_M}+3gI{B3w}ki^zHKvNRMTZT(ZTo*HN|__rx3vk z1%eL=?;5^*{q>v@nv#qsnS6x-Mc4f{R`ac^{UgS3FolKCl9wzb9TfD(pz2rpaAYZ* zuIV@H=8{X`Lh?PoVkn_LXCRguAOM`8#IgNR=zrzgj7xPOj#%@UTr??YKFH91`q(qV z?NrvJ<1eSL$|Pwd^MAMtc_`crS(bE9$xui^Rw8My9-6umO~$4*b@V%(^#=HNHbAda zG7|(`zT>%AmNw_G>R@@b$#UJshC|sK$mT}Egm&vC$X2{*mXKyNJ=z?pU}8cT^BqA{OKoLBZDMUN6UX16SZ zJO23wkpB&X^12CgACu(Ke^PI-7$m=ZnnJQ3g;3u})oJ$V$T;y!HpD&%Ls_U>NHrcK z_Ey?J301P(1)X9?)U#wWql8_AB6)0*w~XXNUI|I(MKSvd6vj!LtFPhnauU!rOV$_? zN(IL6)=w4vBI{-Je&#jhh{We8t^d$mDw_MGCyJ(mT*)SHrG}b;KBO<{PyN;BOFP?a zR&#ImnD0KF;)Xv$q6Bdy9H`Ih1oqa^LjAO_7E<}}pH3Aca^b_RF9%}i5pUGU6b;obcMobjp0064Z zGHit0boxVUhjPXttb%+E=yD%7EXw%(pwpnCGoX6L*buq%=)whtB0et6>09MZ$^`|H zgo)D{71j}t0SS}jJVx+Cor6J^?)mfKp*C{@yV6wNcd02fp9N#5R}NzeaZ=!l1ONHc z2fYWD!>Re1ri?Ujzo`*8eMelk1z<#wfpWA}H$H55aTmc1UsYdhSpnKaae%#o^NDUM zV~#9?#VI+iSWt0V(2(zj+13qVzR@-Jedh1d@p~9*JOI9D{RC=D@3z#$*Z=w8-DWN*Z+Ct@lR`1@uEX^*~A;@l;4(JsR=ZtkpdX)900OJ30Eb8tlJ4&>bI? zEWQ5lnb9^?yeGycwFNgyd+vcYyK$>QOO9(kH0MKGa)o~Ez2UtG zZ;yXdw+m%O=$zGlAz@aI_p2qn5*3ta+;&+T@;n^o8@~VY`r^206H$_m&&k2cnhMb2 zqr804GFzyo>(0z^>*cPCu%aD6XH-Pa^8}gm02oy__kOS_?6SJgb!GL=E`C=D=go&B zLX4y-0$G4;dOZCuKMq!+wYsv>ca>&M_iKBu;ZTWh-rQ1gVOig?Xz7h@vKAZd2h z;NW0OmCnaj>Djnd_7_JRYt0lXF8yj~h9grz3I+KyH}A37;<0DsX8#?)-Lru5n$9T+ z4Tu)n-7+T{A$#-Hx@%6a+B#;dj1=&ZLu4fvr+a%|_1gBxf*5d&iuhhYl_{4X&!_GW z5+h8%hdlJZ_?5L{%wlC}DRO&t2p}&3F+94XQx-N+-7TLz*%FG(wu3+6v+HQIgbq|y zLGzpl7txtIM~-QUc}w%z+IMS4ABm^5N_9*Yw-{ukG!q$faJHd}gQ!+tfG=}pEqDEr z^jUbJt?A2)5XqAN%3=OQv)71*-wRg_Gn;d3`jl_QzXE&C(|N(s``ES&TO3Ml7pCtH zfFmALO9DAlX(D0Ol$Gd7BkzcTfs5sDH2!s!; zTv?uu%NILd?HMRzCZGf`B;fx6r?W=ETL65GNVjfbcVR363|^`*-F%}P6}R<|-yNSC z@Wct>^Z^8xy0~Tc9{McC4FBanNrlfO?Z}y1GC(Wnul(sYh9aH_Xf)%d%?g3%% z(1|`S^5yG`^<3mNuL7XT!7Wf>qrBTcFm@Gh>?RLK>=4-0)?L5jlBB;Fk&6S~{j41s zMB5Cee>&$9CHV6&R^f%`&H3Mq7egvQyrGnKv|I2{=r}+qoWgLvOdn4ea@OI^(341% zO`Kry84&VtD*%1lW{LQklVql(oP+0}RHv$Q#}NOcsz67#50N^z=^bSU`KQRcusP>C z?Pu&Z4r?UGp~^Z1vVgOBqJ8X$M}MfWtvl|X2z=_V!Gx&?E3?K9GiAVNtE+ZgTxsh- zurb9+ugNb4Xnt>@T|1J@Av8UR>PMjVc*e>)Fg*O^m8qn(bVxZm;hy{6TJJC_P<3qrZ0knIq)|mBf5bFaGv$Z5RU^ zKmCa5*DTiUnSa9wvWjBPf%DhzGBBzG zqHU)tP5klXXfHnI8y{Pmbja>^A4`M-XTNCe6q~5&g0Lx%BE0Q_goxf~a1Ue3* z$gPStzxeO<&dV#G0gtYB9BZP9wq$wvOkGEZ-}z5hxna{L#x(*qI53bZ;8NgM--&>g zjHNuVrDo~-3RsfoD;u`do|@zaDfM1jfN2CNraAfQT{1_JAnxE$j^Hc(74s&AaqG+| zQu4@OYaB;>;6R|ynlp~`*{%HaFFj@sVUV95OSp#!W&l?A-^mh`p{pLgD zRP?+?QQEbc{j^w*`$(NAxD~vNbliOuQM9< zeRF8q;oUkra7}?zatCI@`tRMX&UQG)KcAgrGhTY^Xf>aL!>H8OT#;q4OL(~XS17Id zT}=EiJ$av&sCsan|F7{DVBA};Tjc<4x}g`p2%Plwk^vDdXWppUNyHuDiTGUz!sh(H z@JggJY5(wWf>F(;Po3kUAD~J$twnXWDY>n`_7L&SIepsjOk+U5Jl(6Xg&HcR^Q$Ff z%z6IJK;3G^@hmHZMKkIPUZ9SXygbL)OUr+Xd;a;%41Lm1N?q}~gZlF`5@%ejXhU=5r@gs|;Cb@NB| zrvW--{p*{v<&BMvO**!XEd^$MT;fL{xC0=78O8zBEuORQ>g3)$y{n2my|lCvq1dp6 zN|R5XVKqkY`v6Hhrornl2f}3WX1>efH!BrbZ6wFF-~E>e_PkR1kBU|x?jkthx;!+c zlHojd6Ukm&zMmO6vk)l7MH_Q2=dHd>5lk**rC%D->lDE+%~q0-DMEr13RGFnz@gMD-QOCdjQ$10 zI#+*}W@@HBP{O1OxPU~K!@`b_BU{o!7rA8=!>Ev$d`$j zt@}XAF-?(Q+y;PE_D_H=MLx~t46t&W0e@S zc=fZg#S;cj1#z-Gvoc(Vl-9G~9bVzqZiCP3iaM>bd<$^3 zTD(su7()}E>x0l1JAIs;ygI(4?lAmP9>^*by`~#n3RyKRv^d(X-W$H>KOEw6>+ht# zSd9;ttaF&xGy!oN@z%h(o2*f@V@M#NDDK70utej^YvK3TsUB_#%bSgyXYS=9L+t~C zHys$4n)#$4@gM(MViUI;r%4-^fV`OWkM)5DDS|?hEA-&~U5KIYZBALxbG$rQ#?@~)&sa*l3@f4mD8Rg+*U>ur?)yh9 zSNs@|+M_uxf_1=gtXF-ztts9A*RQamf-7*SW%Q#7^+KutIe^;>uw!Grj0LT?^ST>o zNCyGCht8r9@-qrn@V@WKsY>Ecb90s=FMnB_m^OT?bSonT%b^Q#j@PG2vDX*XxICS| zxcpjPUQ`lA70aK0`zgoJ+t5u%$OTnSRtNyOY%t=jMN35=V6FkuIHtA*BCem&Ed|UR z95CwYISNLeQMJC8jf?j}M}c+$mhCX#hWf-b+TlGg8MtB0Fqh9#1{Lm0lX*UBLM7>dN=ob3?5G`VFrK5NLs`SI4;j$|W%f_#$Lsu4~GjP_o(2I4wzSDis zqJ1A#R=&QtK=(LL^q!#e*`|~#Z#mI}>9qPZ{A#%cDYfD-$R&Nb zAnLzbSz9aDtC4>n>6L&mNUtkgjWy+DN%=Y?s(p#oxv9eNl*_6}fih)(eOTffSAkNa z$c5=rRV6|KFqWNFkjtAi?G_LC1}?3 zfQR4r!gX&FlXK_w&SYor#W5ZY;>E)tT$8D zi0^?D@X>@Jz4&~xfu&+g_5F1q+;h@<)hSp4POsaW(>54oOqA@J)$jI?Endg5>1Iax ztcslRMGPd|cANn(V^sfXj@Yd=<5_I5xr72y1t#&<)7aSS1U;#sguP!A0@|23#ULrQ z)XmG!mphfd-eya8;My_o2*iq{@f+-S8NN=39=VTKPR2A|dp1-&iZ^K~;O7 zgsEtrBP@u-Q@~SgD>H&tmNT9uttBP4I2EV_1|Xf1sJ_LuW-fQspM@lR6bzqO_UYr| zsD4tT6J^OkZDXHO+&g_B?&nV~QUO0^nmqR2;~mCTyGrrePyKGWH1|6vJ1~H;%;y2T z%nALSxn_8K+5GUhIK3y;c~P8wS)$E-1=#lLciAC}`%5Rf9ZNf+iJNG%tkcFhkD|!B+8;kR)d$2W#6z;`&@m z#Vnpne<}X(h^j@QGp}#s%$$?&6uj5o^`Y_dN1+=-1t`l# zy{O>7$+S}c>i5O0=INQmxb(3UqdZL_=|0F^VZdK)jy2T1=*G*^{_%bi3!Si1EmvAD zYFf_O`5(wzdLpR)GKS&^yIUO0fqa?K9{)2r&}mPh3RJYWVx>xW3-8$J>`#}l>{~~_ z3S86Oqux1@SJVLAsxxmr?BrOHQSy!>Yf@?dK&`}x!6)9<1I&$(cp$0DSdXQ8%nyZNLE!}=;mC@9@we1A^qY| z33*GifjN&=G9}uWq^9MY{?V)J=PG>q&1cAxj29~Gt6ZZS1=yyUrVb=6GD4k8jgci1^3n4C28U)euM}-=6jl zPJJ&(!2c=o7xvgi zM^540Op)}rBT9r#jJw5TCNjf&z;DL8>)(g=fq}>cVf&b;PR!5CCN8ehjv<7&cLq_@ zO`HPzD$7qS&Z$!3varF-=a}aLj}`|Vk$J6Vmopo0cIf^!Xa|ASwF4jpB1@};a>KE) z1Ra;-8i*QOb*{texKY6x_wS7#v52$Upu|%D8;Bzql)m;VNM~HOY@$GSSh;Xqphc<7 z%T3+2j6)>K_Rjmr?yBFvK;}r}zG|TYXRfhjs5)839 zAnS+xNyMc~DV$^>plf{b7ED+#0h{sBnRD`xy< z|Ett8Li054wVwe6Xy*Ihmui>NNoofxe`*}RoBNs#bDgdFx5hywaUbJ1;S6A{fncq0 zlDp=?AeJDV{K<-isus*x!C@+G!Sj{+(O(lFNrHfeGYF)Xc^b40$uTstUQzNX?u=ze zV#XR9$Fo_ZiP7FQEl_FD<*7e~v%9^XYIw3K%L(d22o4Td`CCy`Zj=|!D+ElzcBx*; zyUvBm!0C;G;g&KFz#<@cz`*Uwd0ZTHP%d7upyPPkCo`F^R~@f!_hJ_QW=v{MYW0Ao zi%P`W;Y20O$`3QF-Hxucik*)7zy6+Hb>V1BD$sWu7-&i++j?%9h1mGuzI=P* zQN)Tt*8#91aZ)s&x4Po|gi@v{_;eAr+;ZPEaH=k@4zq49FD8j)!7=?|M4+(wB#Z6> zjh6Hd>&Zc~OC1@+fCF-qn2v;M^Dto zJKOP+xSUWT;eKLq%3giYSNk_z!}UH6k(Vxx9{UlJ-nkqeT_@;yV7_%pdY~l}Nj+Vr z&nNsqr*eq4)9;0FtDQ>9RRU-MEFpYDES}1X_{lxr^EU|cvy+_UV_1d-len6s3GAb& zjxwQCsGmq}(^;Pbx*R4W^HzyjhByuyBA|@3^+P zdZcPPuy)RXM;`n8Rs8~4)wYvGHis9DxUlFyQ=sP#jXvQ2I=J574ZLgn+BW@77Jl-C zAJyPZbuN^zD{L4J*&sv}^{_m=PbaogS)-)re!gHvANH)2_4B7a$`g9Em2eKfSn)yL zhoc^tu{}zgh|u3r2jC-D>CrtwgtYSiUuPMq6scCiS< zAO5fT?NP+taG&4aLGuj}^zvyZ8=KUzAscS4WbBPuhJ0myZo-5xfp4PI7ds-ts?-0L zt*$h<5xmuPOMS&wNLMDe=c(Y-K?jNe%;xrilbGi3!6htQh+B{?OXsVJi~1* zds-d)=rjGLf;`vdl>|XO|NA4I{*T~%%fjB>=3U#}^@3D#)sCHz(JUGwZ$v}-3mdF| z<^ZgsFSMj2Hg?4Y0Em~My=c|$2Mo@5(9&1Ouo&a^Fvd}}Rpy-6W}eWhm1XL1?|jQj zrC+~ld+^$uU`r1I_XKUx&oaGqdEsD@VTOd_(UrJ$S4Sw(L#w}~UVFnF3MaRvpucPF z=O8ltY|CPr>CP@yUkK6RWyaTM6%>b7Du%~5`o>RQ?}wLT1tiOGuqAfeaSU4CE%Y-_ z5MjGqN0KOeW}U;ySaZUjkMF)%aXD6Cjql~hyS_9Cq4E*ZRLSQQY5(}ndOBh_Xw7FA z;WXsJZSK2c&9FTO0iS1;B)MoMdu@yUe+>rZZA+u0~NdFXy!E#*3~-9>q)C7;5^qA-UVe65Sh>VY>R6}-8D~v z&JCY!ICBKmxN^Bx*;_kjCvEDv!(SbvBGdooYjbjCA~R6cM#p2M*J9|_p7O(b%u=^} z6)2S1=V0w;*d!xw8?qUSU9w1$}b0t~Opj9RW8H73f9S|kXtS4&;e5{yskywg&d z86`zy!_PwoKu_K6Xhg*(Kzw=MZAMYLnVbYX5PlFuqkr2cTRl46gKgaq>j=;IY{HmD z7ivala=iZY{Ze2_p$b)W#uK00y>Jze>%+YgE0y6(>(vP)3j70r{ne?e<;Io$ow`e_ zp}t9syS{$hx~^@DZrI(!+WC>ET9N{LuFtZ1{I!hL{ytf4u$UllSlMDW2=!mfmz=#{ya* zneXuXw8r6t-~Mn_E++8@mmHLG%=>=O{3rRarBpRLiLCC&V;_TBn29CI`?Ey?%j<)||D{t`fL>M-C&q3nm)CC%?IDGkGxULb`$!VG; zRx_f79?p1#yn4ei2t$`53Wjx)Xc2r3vz<_ExY*=^M!y#RhZISw9{{*SF;z&F(OIeHH)Y#iL(WT8PbRe|FXTDKv8Z zBW@@@O~dg*-BAF4jO*C@&ER-~+wCjTz4Eq;A*y>>#n`Orn%^!w|7NNSGqSh+yZ&2K zvDfO|@YJb(KQQs||Fv@E|4{GWe-J~9t>jt~MM>dS*A~MhG`Pqz$X-_|6|#(FGJ}Xx z86(YAwye!!h{kB_ZIYNQk!=PU#MrmS`h88G`zL&VoA*54@7MdhU$1k{>zwB~ujjZ# zhY*~SM=;lJG0aPPdM$Yu87g^FO|9_F8{tyz!G%UBdy3S6EY0@7JYP||)n-syNG-p6 z!8~=gk`T&;*-1F*uTnmey$*uP6YEZ3f5~cH3Dn3CGxDAlT|W_vi&}e?99TQ=0h4q9 zm85U5!|X00aaqr<$(-#fD+$P}M_x~J37q|j;KZY^>ZdldNNukAjzdJR+Gpnyv$KFY z5A2QBs!{%=3=r9Q+QB=g(f+KOjDwiEONmtTD<9DBr2pJ-aoVWRN{|OdrtaS-_T$wZ zEbo+RP?X^Nbgl(;Ecb+GK1&0sHUWUTradAPh~8H^kqN*wHva*=R=P7?Gz7#<>b*eJ z#US&2w-0YQ%Q#CYTNLO}me&>9nlqm1ptv6f89F^Q0S!&qTKng>z$nJHH}hL_q!5^I zBy&&C2Y6kraccbMlRfID(y_4imN=R52fvh)2_-2j73&*9x4FeR;=~Zd!eaPOQo}b= zmK#Rga#hza^kxzHvSmC|M(V>l#^BEPRf7qtp&W^NwRO@)zNcI01!z<+f;QEVp^9rO zw+#JO0+%2@c1z{(ee=l&WOabm?8j`(&vg{Kj|Ofw0juo`^ADYAw>Z`O(@*Cc@|6n3 zzQ84AzqPDK33OyIPB_P8X>KQMD5&>J@m6%V41cSNx_JK~Xxu+!o&E@Q*d*+8hVIaCB04MF3wL&8?nQY`c;%OjXY>gk%{y@GY|o*`is8ILT!^`(9$_#v(5*LvE6;r=8K;(~|l0w9l7+LD}%E2>veA%B5~`nM*vrtrO_kNZ5g|3f}m4 z>dhfA?=nDy`|8qV-#w77uo(TXl-_1+9j_*ncu~SQsQt~jZaYojjH|;M%iX&*``KzK zmeRkroWj_zJ02Bmt+Vn#S*g9n>MyfY%i+ZOHk&N&+J)($m1$~?CC8g;AHOYWPEuu%cLKFnZu5Gh&*q$pK?y<=2?D{PQ!TVWn3_(#RCc<3%xKxmE2`<%K_i~Rz(&!C=B*v}& zmD;*c>wtj9u~u{_a;T$YDwCaWGd@$&|N2G&`K@;D@oStCRyIAV33?-(t9^{@U1~A) zbh*tSzdh+v1~`x9^0m*~VeO}^iGfXtAAP^xZevH72G;-Yd`#`Lh2qbw^M5X0*Jyn* zxG>J~4XE$Oz&|e(`8p$Ozfmq8G~snYqZ)?kF4-&GicPR*&rV$Va6Au@lmJdSE<>c9 zFAcL6TDHda-&sbcQg?bp{YYcZvKS#Lx+VQZQ>38DsP1M!q%kSLEC|^i+Dk4lq$VCm zPY!#zEZrE#?wdEDWy9Q-YA&ZLQ9)mO^Hkt|FKoX9Qdjlnr;x;yD0iiA$aG78ywp-m zLNT%R--rw|%1`Z^nf1OE%^IhK)9W&gRtMI^_L=|};Nls!b~Iyp%Mq_zUXu+e8r}4pKgtd~-c7r7 z!8z(?nAb3MdL10x{*mK(dT!0dNDVsQus2c~vJ|6zs+>t|jkuJrBpP3kkW6(QJ(igC zGei&Z_V%E_$o($`e_zPvFdeJ@)m8>mbubU%8js@Zu#c~A!C<5xooFC5!yuzAEY5-V z=U|MgHtL^WwQEIB7w$2v>nGnh_g>1hvMqzL@FC-%(izvH8!(*DT-QFf&1Kf)LjH?8 zc%miKOCmxS+kDk?XM8*kc+Cj`2`9$fQMXU}(is~}&CE*iKbFcz#OzfclIlohQIMdi z*W%a1+21t%CS$fY*`Nd}tboAimvK#Utd)7Q_&tW3-=l}q)Z*_f^@^~E&tAT3(%fkG zBFpWoDz!@KF~=(I(YAqEkhfHWSSQL6@f{k(I13ZC_6f}ZdlKWv3iVdM?pK=`e2+J4f;sOLke;rzM?GHjXOhX!rY%X6=B^@W*mtDhs4*B zxr(0Hu&NHCINsT)wK-_#8NmP0;q9 zabt!lKz{wKU}C?tYPvE)TUOcY`sBvsu@d>vpRBQsnOnBk$LexQ5TZN~85}I#oC#ry z`GP#sbRHJ&UvM|6-Am`-#sp5t?V2y9Q=B!*xbCJtLUQOIn-0Qiatidnl5eWsy z?EHYcT9D9q8S(7d-{-H|1rwA|I5D^4z>Vcna!650r;xaw2Ydeh(X|NyhzuZ0+GRpA zi!J6F-~9gPl>DI-e7nGoQQ)N>DuoTd&J+N>N|@yRVPUsoP?-8znwo;&_^2j&dNBv1 zUf-LL=1_6exBI+Ta8h^x(~R(ai1EYJG_F5+)Gc}~;kh9dq0OG|QiV*!!V%P<&nl)O zvPOgws78pwBZ{xTt$|rptI7yJm~@Km>=vN&g|S!lAE0Ug_ZLIb2f41&ouNZws(k-D z)_QlhYJdIUdSAWnmu$vDYmeSE&mJm$Ui4U|BTe#9UBB1J$^>Pq)c71hBgAH(^QmL> z^M0OK+PdEx5eW8E#lYB(`|1G_oqglWl+cVPt9qPxfGo#=<=T~pcwzt&Q-C!TIu;-K z=i?ICSHe2WzFf7j>jp}R>1VmfMxVOQT?i*czd4Cr_ugI@ORg}cSc%S4A0;|!7yOvH z9v&+@p3T{+TWGW?p^abYX&F3wP0dT&_r&7AhW~a@4dN zu!0w1tVkOW@b`3OQcO09j%i22LT|-bt!$T%=I~DELS#Y0KN$TRH0w7t~gk`T~NX9BVzIeXQ6pydonfG8K7$zgN1m41SVWl938Prv=6 zkD(i7WG-bl?h;Y2OD(Qd%$^}B4Wy%Bo+o})Ppbtm(evf9YNAaZsN^7FO=V>;-d;^P zi0T6^&u1np6CVs5p##56#*2#28{n#HgQguFyT?jcRH(+CwGVd2v+$7>*Aw>@8*N%O z?<-OX6NBCk8tDOmM}onAXQ&6gR#+ws^+EsT3&FWE!fqI&C_C^JHap1H?VTG#cjVso zt28a7F7TBFA*HtG2wGde{CW_Nn1^$XvR+V&inJ=Hw!4fnjKkl}*$0v%4)0Bk`@3~I zJ9BN>p8<xoBr|amp?jM~v*-rQ$dh`5`Z+Xzas=+H*C`OQL1t^a1nu9h!E~7s5@gn&O~# z60-@|N0e`SMx1Rqs#LG)=ieRH6GoBkpjOy*IC{?wz+o4zoYKizRl5I&m^oddrAtU9 z_+c&RZ<7LOn)IN#EKS~onz940a<0voH!9E2-Jk}A?|Pe?fbu^ZVn*S9ospKJqRp#H zMPu}Tle|rRBQHDJt)#<)r*-_kQL{)l-rfB8zQy9#E1^c_qSi*{Gr~XbYJ$+&wR_Xg zZOEOz05E7}Ej~p`J>%Di?%pFF&(hL#BIYt^{>UEM@KV>iT2<4CGo9xSL@pPwq2A4( ztYvpE7}JKtIcLTx79e1rVrq8H3TO||5CmScIHL!G zaBD)qF-=$zS@3mG<2Tqw9j*&(yHvO89~Ih|HPpI*+|ADN8S_E64a{5yX>~U0qStUC z+dG}O85Xtm-SQx@yuCK0g6<`MLO5fggT8CgdGaj#pr?N`Km4{#AC(VZ|Diy0_LgTZ;$^Q?(O>8 zQo`w4CyC`ZyM0!|Yyh@e!<)p`bqI;C4u&^QA7%iLS9X+-Ye$6iUYQ1IU7%ZA4BIQx z&C1GDQ6_Zs<@2v$T-OH66Y&EcUkCtf{eBRv-%vk?Ku53iZgm!2*&frAMvUC)w|5@X zePFhzEEqoi06?wZmH79SZf*A2fP|IkSRo?Lz0m67QWdp4YVjx!rMF57LaVzy$rnYN zL*5_e1LuDVmG^feodHEW>2l-TT0fbfS!eQ%=U574}BAl2qw_)&Ppmy98fDw!0m+qBT z<-L0-*Skx0_hfs1!p7#05A41(@#~EyH(*^K zTd&^Zh+w6h$F_F5o!oB@fcSq_juHK*ry3#@?UK%p2l-p_c4%MhIPf`P@mW@DwZa`K$6uQq$ zy$*#*!q}KDDyad$=ePM3MoF0m48}Vl8}`Jcsq*77kbYh zyv1zQ{1ly^TlLG&lhelb+f&0WM@2y(-21Q)}v=s9ftf%SSe2?}Y*<~J68vbQ%&w=?k+w1kSOPWS6M>4+WIo;8#)U76MX zhO9H%-bg2S3|L4&Vqkn%l==_AJ>#JGRd6CsI%yOq1pOSEjvcF=>u1%vPw{P$ZwSF2 z`AK<#%?+_~(|u}I$`|KZm3p6|GbWWW;?s+w5JSSz6)Udgjb64xZFh0w z1RQ|j7#gm>&El@QU;~SPYf@i%Vb#WE8ek`2IZ((028&-T@D?Ih!}XWDL>QmjSa&Ke zu!3h4+*1^Z{-SS&;+`%v`$~L5Sd$CM|ILp&A`@PIljq!IsHu}FRE z<8~{$0wCbI?s6E?DLwswWA$17N4p@;vg>ZC#rpb%zeJK5RKb`CGf*^quPB3f3Uaq; z9b9H~W#2jJRyf}ZzYV(v)^9$dlHyvl43P=AXF86dGLZM${H3;#+4m&poODI(=-lw( z$)xgdmz$kP3F=6 z4;;KgHGV<^fe{jwfwFMk zUSaHnNdE!M-p5)>RMp(vglxTpS!zdl%24EW9J&H=k`QU5^vXKP(BE2p*#5}atx}FbSqs7+Y+<^ z(`}CfVWJk89sh4V{@*H3pm@E?v9W;On%;gDcZ~l)RV9$(0EjTDKzIRuFZT2Vzc-&)pG6yhWX)(01)80!n*k+bmFg6o}WE!yqR2kRDjtw3XQck*T1 z!NDqDXVuI!a2G;M+YC#IR6&T79RJC$HBh{B$)u%Vvl0&UlkNq2B`O7^f^cG0S0637 zmtf~V*pWavVNKd}bao)b)?NoN&hbUcO@H#FEvx!c<69;cOie&FE#${X8lc*X`IBFp z2Xw}9zMCfeA7+x^O%MotA78n_CEz#v|GM;W=-3wOP-A}`g|lP%gIk*0no&)C;{Fds CD8?QD literal 0 HcmV?d00001 From 925745bb0dd3769c10721d36a7c1e380183220ed Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Fri, 17 Jun 2022 11:20:00 -0500 Subject: [PATCH 04/42] updates per Mark Signed-off-by: Hannah Hunter --- .../quickstarts/bindings-quickstart.md | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index 9a7469b0d..ec68f47ec 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -11,7 +11,7 @@ Let's take a look at Dapr's [Bindings building block]({{< ref bindings >}}). Usi - Trigger your app with events coming in from external systems. - Interface with external systems. -In this Quickstart, you will schedule a batch script to run every 10 seconds using an input [Cron](https://docs.dapr.io/reference/components-reference/supported-bindings/cron/) binding. The script will process a JSON file and output data to an external SQL database using the [PostgreSQL](https://docs.dapr.io/reference/components-reference/supported-bindings/postgres) Dapr binding. +In this Quickstart, you will schedule a batch script to run every 10 seconds using an input [Cron](https://docs.dapr.io/reference/components-reference/supported-bindings/cron/) binding. The script processes a JSON file and outputs data to a SQL database using the [PostgreSQL](https://docs.dapr.io/reference/components-reference/supported-bindings/postgres) Dapr binding. @@ -31,7 +31,7 @@ For this example, you will need: ### Step 1: Set up the environment -Clone the [sample we've provided in our Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/bindings). +Clone the [sample provided in the Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/bindings). ```bash git clone https://github.com/dapr/quickstarts.git @@ -39,9 +39,9 @@ git clone https://github.com/dapr/quickstarts.git ### Step 2: Run PostgreSQL Docker container locally -You will run the [PostgreSQL instance](https://www.postgresql.org/) locally in a Docker container on your machine. The Quickstart sample includes a Docker Compose file to locally customize, build, run, and initialize the `postgres` container with a default `orders` table. +Run the [PostgreSQL instance](https://www.postgresql.org/) locally in a Docker container on your machine. The Quickstart sample includes a Docker Compose file to locally customize, build, run, and initialize the `postgres` container with a default `orders` table. -In a terminal window, from the root of the Quickstarts clone directory, navigate to the `bindings\db` directory. +In a terminal window, from the root of the Quickstarts clone directory, navigate to the `bindings/db` directory. ```bash cd quickstarts/bindings/db @@ -118,7 +118,7 @@ with DaprClient() as d: ### Step 4: View the output of the job -Notice, as specified above, the code invokes the Output Binding with the `OrderId`, `Customer`, and `Price` as a payload. +Notice, as specified above, the code invokes the output binding with the `OrderId`, `Customer`, and `Price` as a payload. Your output binding's `print` statement output: @@ -166,7 +166,7 @@ The output should look like this: When you execute the `dapr run` command and specify the component path, the Dapr sidecar: -- Initiates the Cron [Binding building block]({{< ref bindings >}}) +- Initiates the Cron [binding building block]({{< ref bindings >}}) - Calls the binding endpoint (`batch`) every 10 seconds The Cron `binding-cron.yaml` file included for this Quickstart contains the following: @@ -185,13 +185,13 @@ spec: value: "@every 10s" # valid cron schedule ``` -**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding will be invoked. +**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding is invoked. #### `component\bindings-postgres.yaml` component file When you execute the `dapr run` command and specify the component path, the Dapr sidecar: -- Initiates the PostgreSQL [Binding building block]({{< ref /reference/components-reference/supported-bindings/postgres.md >}}) +- Initiates the PostgreSQL [binding building block]({{< ref postgres.md >}}) - Connects to PostgreSQL using the settings specified in the `bindings-postgres.yaml` file With the `bindings-postgres.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. @@ -232,7 +232,7 @@ For this example, you will need: ### Step 1: Set up the environment -Clone the [sample we've provided in our Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/bindings). +Clone the [sample provided in the Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/bindings). ```bash git clone https://github.com/dapr/quickstarts.git @@ -240,9 +240,9 @@ git clone https://github.com/dapr/quickstarts.git ### Step 2: Run PostgreSQL Docker container locally -You will run the [PostgreSQL instance](https://www.postgresql.org/) locally in a Docker container on your machine. The Quickstart sample includes a Docker Compose file to locally customize, build, run, and initialize the `postgres` container with a default `orders` table. +Run the [PostgreSQL instance](https://www.postgresql.org/) locally in a Docker container on your machine. The Quickstart sample includes a Docker Compose file to locally customize, build, run, and initialize the `postgres` container with a default `orders` table. -In a terminal window, from the root of the Quickstarts clone directory, navigate to the `bindings\db` directory. +In a terminal window, from the root of the Quickstarts clone directory, navigate to the `bindings/db` directory. ```bash cd quickstarts/bindings/db @@ -314,7 +314,7 @@ async function processBatch(){ ### Step 4: View the output of the job -Notice, as specified above, the code invokes the Output Binding with the `OrderId`, `Customer`, and `Price` as a payload. +Notice, as specified above, the code invokes the output binding with the `OrderId`, `Customer`, and `Price` as a payload. Your output binding's `print` statement output: @@ -363,7 +363,7 @@ The output should look like this: When you execute the `dapr run` command and specify the component path, the Dapr sidecar: -- Initiates the Cron [Binding building block]({{< ref bindings >}}) +- Initiates the Cron [binding building block]({{< ref bindings >}}) - Calls the binding endpoint (`batch`) every 10 seconds The Cron `binding-cron.yaml` file included for this Quickstart contains the following: @@ -382,13 +382,13 @@ spec: value: "@every 10s" # valid cron schedule ``` -**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding will be invoked. +**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding is invoked. #### `component\bindings-postgres.yaml` component file When you execute the `dapr run` command and specify the component path, the Dapr sidecar: -- Initiates the PostgreSQL [Binding building block]({{< ref /reference/components-reference/supported-bindings/postgres.md >}}) +- Initiates the PostgreSQL [binding building block]({{< ref /reference/components-reference/supported-bindings/postgres.md >}}) - Connects to PostgreSQL using the settings specified in the `bindings-postgres.yaml` file With the `bindings-postgres.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. @@ -429,7 +429,7 @@ For this example, you will need: ### Step 1: Set up the environment -Clone the [sample we've provided in our Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/bindings). +Clone the [sample provided in the Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/bindings). ```bash git clone https://github.com/dapr/quickstarts.git @@ -437,9 +437,9 @@ git clone https://github.com/dapr/quickstarts.git ### Step 2: Run PostgreSQL Docker container locally -You will run the [PostgreSQL instance](https://www.postgresql.org/) locally in a Docker container on your machine. The Quickstart sample includes a Docker Compose file to locally customize, build, run, and initialize the `postgres` container with a default `orders` table. +Run the [PostgreSQL instance](https://www.postgresql.org/) locally in a Docker container on your machine. The Quickstart sample includes a Docker Compose file to locally customize, build, run, and initialize the `postgres` container with a default `orders` table. -In a terminal window, from the root of the Quickstarts clone directory, navigate to the `bindings\db` directory. +In a terminal window, from the root of the Quickstarts clone directory, navigate to the `bindings/db` directory. ```bash cd quickstarts/bindings/db @@ -508,7 +508,7 @@ using var client = new DaprClientBuilder().Build(); ### Step 4: View the output of the job -Notice, as specified above, the code invokes the Output Binding with the `OrderId`, `Customer`, and `Price` as a payload. +Notice, as specified above, the code invokes the output binding with the `OrderId`, `Customer`, and `Price` as a payload. Your output binding's `print` statement output: @@ -557,7 +557,7 @@ The output should look like this: When you execute the `dapr run` command and specify the component path, the Dapr sidecar: -- Initiates the Cron [Binding building block]({{< ref bindings >}}) +- Initiates the Cron [binding building block]({{< ref bindings >}}) - Calls the binding endpoint (`batch`) every 10 seconds The Cron `binding-cron.yaml` file included for this Quickstart contains the following: @@ -576,13 +576,13 @@ spec: value: "@every 10s" # valid cron schedule ``` -**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding will be invoked. +**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding is invoked. #### `component\bindings-postgres.yaml` component file When you execute the `dapr run` command and specify the component path, the Dapr sidecar: -- Initiates the PostgreSQL [Binding building block]({{< ref /reference/components-reference/supported-bindings/postgres.md >}}) +- Initiates the PostgreSQL [binding building block]({{< ref /reference/components-reference/supported-bindings/postgres.md >}}) - Connects to PostgreSQL using the settings specified in the `bindings-postgres.yaml` file With the `bindings-postgres.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. @@ -623,7 +623,7 @@ For this example, you will need: ### Step 1: Set up the environment -Clone the [sample we've provided in our Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/bindings). +Clone the [sample provided in the Quickstarts repo](https://github.com/dapr/quickstarts/tree/master/bindings). ```bash git clone https://github.com/dapr/quickstarts.git @@ -631,9 +631,9 @@ git clone https://github.com/dapr/quickstarts.git ### Step 2: Run PostgreSQL Docker container locally -You will run the [PostgreSQL instance](https://www.postgresql.org/) locally in a Docker container on your machine. The Quickstart sample includes a Docker Compose file to locally customize, build, run, and initialize the `postgres` container with a default `orders` table. +Run the [PostgreSQL instance](https://www.postgresql.org/) locally in a Docker container on your machine. The Quickstart sample includes a Docker Compose file to locally customize, build, run, and initialize the `postgres` container with a default `orders` table. -In a terminal window, from the root of the Quickstarts clone directory, navigate to the `bindings\db` directory. +In a terminal window, from the root of the Quickstarts clone directory, navigate to the `bindings/db` directory. ```bash cd quickstarts/bindings/db @@ -703,7 +703,7 @@ in := &dapr.InvokeBindingRequest{ ### Step 4: View the output of the job -Notice, as specified above, the code invokes the Output Binding with the `OrderId`, `Customer`, and `Price` as a payload. +Notice, as specified above, the code invokes the output binding with the `OrderId`, `Customer`, and `Price` as a payload. Your output binding's `print` statement output: @@ -752,7 +752,7 @@ The output should look like this: When you execute the `dapr run` command and specify the component path, the Dapr sidecar: -- Initiates the Cron [Binding building block]({{< ref bindings >}}) +- Initiates the Cron [binding building block]({{< ref bindings >}}) - Calls the binding endpoint (`batch`) every 10 seconds The Cron `binding-cron.yaml` file included for this Quickstart contains the following: @@ -771,13 +771,13 @@ spec: value: "@every 10s" # valid cron schedule ``` -**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding will be invoked. +**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding is invoked. #### `component\bindings-postgres.yaml` component file When you execute the `dapr run` command and specify the component path, the Dapr sidecar: -- Initiates the PostgreSQL [Binding building block]({{< ref /reference/components-reference/supported-bindings/postgres.md >}}) +- Initiates the PostgreSQL [binding building block]({{< ref /reference/components-reference/supported-bindings/postgres.md >}}) - Connects to PostgreSQL using the settings specified in the `bindings-postgres.yaml` file With the `bindings-postgres.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. From f7cc3dd2e7ee8ed1f31d893b8cc77d54848e42a2 Mon Sep 17 00:00:00 2001 From: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> Date: Tue, 21 Jun 2022 18:20:27 +0000 Subject: [PATCH 05/42] Do not hardcode Dapr version in sample Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com> --- .../supported-state-stores/setup-azure-cosmosdb.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daprdocs/content/en/reference/components-reference/supported-state-stores/setup-azure-cosmosdb.md b/daprdocs/content/en/reference/components-reference/supported-state-stores/setup-azure-cosmosdb.md index 5595e9677..4542444e5 100644 --- a/daprdocs/content/en/reference/components-reference/supported-state-stores/setup-azure-cosmosdb.md +++ b/daprdocs/content/en/reference/components-reference/supported-state-stores/setup-azure-cosmosdb.md @@ -190,7 +190,7 @@ First, download the code of the stored procedures for the version of Dapr that y ```sh # Set this to the version of Dapr that you're using -DAPR_VERSION="v1.7.0" +DAPR_VERSION="release-{{% dapr-latest-version short="true" %}}" curl -LfO "https://raw.githubusercontent.com/dapr/components-contrib/${DAPR_VERSION}/state/azure/cosmosdb/storedprocedures/__daprver__.js" curl -LfO "https://raw.githubusercontent.com/dapr/components-contrib/${DAPR_VERSION}/state/azure/cosmosdb/storedprocedures/__dapr_v2__.js" ``` From 15d8de06aaae528b1655896e1fb567b1c537c786 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Tue, 21 Jun 2022 13:53:32 -0500 Subject: [PATCH 06/42] build fix Signed-off-by: Hannah Hunter --- .../en/getting-started/quickstarts/bindings-quickstart.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index ec68f47ec..5ebc0ca21 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -388,7 +388,7 @@ spec: When you execute the `dapr run` command and specify the component path, the Dapr sidecar: -- Initiates the PostgreSQL [binding building block]({{< ref /reference/components-reference/supported-bindings/postgres.md >}}) +- Initiates the PostgreSQL [binding building block]({{< ref postgres.md >}}) - Connects to PostgreSQL using the settings specified in the `bindings-postgres.yaml` file With the `bindings-postgres.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. @@ -582,7 +582,7 @@ spec: When you execute the `dapr run` command and specify the component path, the Dapr sidecar: -- Initiates the PostgreSQL [binding building block]({{< ref /reference/components-reference/supported-bindings/postgres.md >}}) +- Initiates the PostgreSQL [binding building block]({{< ref postgres.md >}}) - Connects to PostgreSQL using the settings specified in the `bindings-postgres.yaml` file With the `bindings-postgres.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. @@ -777,7 +777,7 @@ spec: When you execute the `dapr run` command and specify the component path, the Dapr sidecar: -- Initiates the PostgreSQL [binding building block]({{< ref /reference/components-reference/supported-bindings/postgres.md >}}) +- Initiates the PostgreSQL [binding building block]({{< ref postgres.md >}}) - Connects to PostgreSQL using the settings specified in the `bindings-postgres.yaml` file With the `bindings-postgres.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. From 0ebe9cfa6db42ee3166f4fe92dde9964ade30e25 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Tue, 21 Jun 2022 15:11:32 -0500 Subject: [PATCH 07/42] update to README Signed-off-by: Hannah Hunter --- .../quickstarts/bindings-quickstart.md | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index 5ebc0ca21..9f6f87c4c 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -71,7 +71,7 @@ CONTAINER ID IMAGE COMMAND CREATED STATUS In a new terminal window, navigate to the SDK directory. ```bash -cd quickstarts/bindings/python/sdk +cd quickstarts/bindings/python/sdk/batch ``` Install the dependencies: @@ -83,7 +83,7 @@ pip3 install -r requirements.txt Run the `python-quickstart-binding-sdk` service alongside a Dapr sidecar. ```bash -dapr run --app-id python-quickstart-binding-sdk --app-port 50051 --components-path ../../components python3 batch.py +dapr run --app-id python-binding-quickstart-sdk --app-port 50051 --components-path ../../../components -- python3 app.py ``` The code inside the `process_batch` function is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks like a route called via HTTP POST in your Flask application by the Dapr sidecar. @@ -123,9 +123,11 @@ Notice, as specified above, the code invokes the output binding with the `OrderI Your output binding's `print` statement output: ``` -== APP == {"sql": "insert into orders (orderid, customer, price) values (1, 'John Smith', 100.32);"} -== APP == {"sql": "insert into orders (orderid, customer, price) values (2, 'Jane Bond', 15.4);"} -== APP == {"sql": "insert into orders (orderid, customer, price) values (3, 'Tony James', 35.56);"} +== APP == Processing batch.. +== APP == insert into orders (orderid, customer, price) values (1, 'John Smith', 100.32) +== APP == insert into orders (orderid, customer, price) values (2, 'Jane Bond', 15.4) +== APP == insert into orders (orderid, customer, price) values (3, 'Tony James', 35.56) +== APP == Finished processing batch ``` In a new terminal, verify the same data has been inserted into the database. Navigate to the `bindings/db` directory. @@ -272,7 +274,7 @@ CONTAINER ID IMAGE COMMAND CREATED STATUS In a new terminal window, navigate to the SDK directory. ```bash -cd quickstarts/bindings/javascript/sdk +cd quickstarts/bindings/javascript/sdk/batch ``` Install the dependencies: @@ -284,7 +286,7 @@ npm install Run the `javascript-quickstart-binding-sdk` service alongside a Dapr sidecar. ```bash -dapr run --app-id javascript-quickstart-binding-sdk --app-port 3500 --dapr-http-port 5051 --components-path ../../components node batch.js +dapr run --app-id javascript-quickstart-binding-sdk --app-port 5001 --dapr-http-port 3500 --components-path ../../../components -- node index.js ``` The code inside the `process_batch` function is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks like a route called via HTTP POST in your Flask application by the Dapr sidecar. @@ -469,7 +471,7 @@ CONTAINER ID IMAGE COMMAND CREATED STATUS In a new terminal window, navigate to the SDK directory. ```bash -cd quickstarts/bindings/csharp/sdk +cd quickstarts/bindings/csharp/sdk/batch ``` Install the dependencies: @@ -482,7 +484,7 @@ dotnet build batch.csproj Run the `csharp-quickstart-binding-sdk` service alongside a Dapr sidecar. ```bash -dapr run --app-id csharp-quickstart-binding-sdk --app-port 7001 --components-path ../../components -- dotnet run --project batch.csproj +dapr run --app-id csharp-quickstart-binding-sdk --app-port 7002 --components-path ../../../components -- dotnet run ``` The code inside the `process_batch` function is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks like a route called via HTTP POST in your Flask application by the Dapr sidecar. @@ -514,9 +516,10 @@ Your output binding's `print` statement output: ``` == APP == Processing batch.. -== APP == insert into orders (orderid, customer, price) values(1, 'John Smith', 100.32) -== APP == insert into orders (orderid, customer, price) values(2, 'Jane Bond', 15.4) -== APP == insert into orders (orderid, customer, price) values(3, 'Tony James', 35.56) +== APP == insert into orders (orderid, customer, price) values (1, 'John Smith', 100.32); +== APP == insert into orders (orderid, customer, price) values (2, 'Jane Bond', 15.4); +== APP == insert into orders (orderid, customer, price) values (3, 'Tony James', 35.56); +== APP == Finished processing batch ``` In a new terminal, verify the same data has been inserted into the database. Navigate to the `bindings/db` directory. @@ -663,19 +666,19 @@ CONTAINER ID IMAGE COMMAND CREATED STATUS In a new terminal window, navigate to the SDK directory. ```bash -cd quickstarts/bindings/go/sdk +cd quickstarts/bindings/go/sdk/batch ``` Install the dependencies: ```bash -go build batch.go +go build app.go ``` Run the `go-quickstart-binding-sdk` service alongside a Dapr sidecar. ```bash -dapr run --app-id go-input-binding-sdk --app-port 6002 --dapr-http-port 6003 --dapr-grpc-port 60002 --components-path ../../components go run batch.go +dapr run --app-id go-input-binding-sdk --app-port 6002 --dapr-http-port 3502 --dapr-grpc-port 60002 --components-path ../../../components -- go run app.go ``` The code inside the `process_batch` function is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks like a route called via HTTP POST in your Flask application by the Dapr sidecar. From f0f9e421fb9260f752a9e1656ccd698b3e5c8610 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Tue, 21 Jun 2022 15:19:50 -0500 Subject: [PATCH 08/42] fix image path Signed-off-by: Hannah Hunter --- .../en/getting-started/quickstarts/bindings-quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index 9f6f87c4c..371103f8e 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -13,7 +13,7 @@ Let's take a look at Dapr's [Bindings building block]({{< ref bindings >}}). Usi In this Quickstart, you will schedule a batch script to run every 10 seconds using an input [Cron](https://docs.dapr.io/reference/components-reference/supported-bindings/cron/) binding. The script processes a JSON file and outputs data to a SQL database using the [PostgreSQL](https://docs.dapr.io/reference/components-reference/supported-bindings/postgres) Dapr binding. - + Select your preferred language-specific Dapr SDK before proceeding with the Quickstart. From 6aee451453188f8fc4c2c3eafd87c1f2f4df5cd0 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Tue, 21 Jun 2022 15:47:43 -0500 Subject: [PATCH 09/42] updates from Nick Signed-off-by: Hannah Hunter --- .../quickstarts/bindings-quickstart.md | 63 ++++++++++--------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index 371103f8e..8c99bb21c 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -80,13 +80,13 @@ Install the dependencies: pip3 install -r requirements.txt ``` -Run the `python-quickstart-binding-sdk` service alongside a Dapr sidecar. +Run the `python-binding-quickstart-sdk` service alongside a Dapr sidecar. ```bash dapr run --app-id python-binding-quickstart-sdk --app-port 50051 --components-path ../../../components -- python3 app.py ``` -The code inside the `process_batch` function is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks like a route called via HTTP POST in your Flask application by the Dapr sidecar. +The code inside the `process_batch` function is executed every 10 seconds (defined in [`binding-cron.yaml`]({{< ref "#componentsbinding-cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks for a route called via HTTP POST in your Flask application by the Dapr sidecar. ```python # Triggered by Dapr input binding @@ -94,7 +94,7 @@ The code inside the `process_batch` function is executed every 10 seconds (defin def process_batch(): ``` -The `python-quickstart-binding-sdk` service uses the PostgreSQL output binding defined in the [`bindings.yaml`]({{< ref "#bindingsyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. +The `python-binding-quickstart-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "#componentbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. ```python with DaprClient() as d: @@ -187,18 +187,18 @@ spec: value: "@every 10s" # valid cron schedule ``` -**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding is invoked. +**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression]({{ ref cron.md }}) that specifies how often the binding is invoked. -#### `component\bindings-postgres.yaml` component file +#### `component\binding-postgres.yaml` component file When you execute the `dapr run` command and specify the component path, the Dapr sidecar: - Initiates the PostgreSQL [binding building block]({{< ref postgres.md >}}) -- Connects to PostgreSQL using the settings specified in the `bindings-postgres.yaml` file +- Connects to PostgreSQL using the settings specified in the `binding-postgres.yaml` file -With the `bindings-postgres.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. +With the `binding-postgres.yaml` component, you can easily swap out the backend database [binding]({{< ref supported-bindings.md >}}) without making code changes. -The PostgreSQL `bindings-postgres.yaml` file included for this Quickstart contains the following: +The PostgreSQL `binding-postgres.yaml` file included for this Quickstart contains the following: ```yaml apiVersion: dapr.io/v1alpha1 @@ -289,13 +289,16 @@ Run the `javascript-quickstart-binding-sdk` service alongside a Dapr sidecar. dapr run --app-id javascript-quickstart-binding-sdk --app-port 5001 --dapr-http-port 3500 --components-path ../../../components -- node index.js ``` -The code inside the `process_batch` function is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks like a route called via HTTP POST in your Flask application by the Dapr sidecar. +The code inside the `process_batch` function is executed every 10 seconds (defined in [`binding-cron.yaml`]({{< ref "#componentsbinding-cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks for a route called via HTTP POST in your Flask application by the Dapr sidecar. ```javascript - +async function start() { + await server.binding.receive(cronBindingName,processBatch); + await server.start(); +} ``` -The `javascript-quickstart-binding-sdk` service uses the PostgreSQL output binding defined in the [`bindings.yaml`]({{< ref "#bindingsyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. +The `javascript-quickstart-binding-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "##componentsbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. ```javascript async function processBatch(){ @@ -384,18 +387,18 @@ spec: value: "@every 10s" # valid cron schedule ``` -**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding is invoked. +**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression]({{< ref cron.md >}}) that specifies how often the binding is invoked. -#### `component\bindings-postgres.yaml` component file +#### `component\binding-postgres.yaml` component file When you execute the `dapr run` command and specify the component path, the Dapr sidecar: - Initiates the PostgreSQL [binding building block]({{< ref postgres.md >}}) -- Connects to PostgreSQL using the settings specified in the `bindings-postgres.yaml` file +- Connects to PostgreSQL using the settings specified in the `binding-postgres.yaml` file -With the `bindings-postgres.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. +With the `binding-postgres.yaml` component, you can easily swap out the backend database [binding]({{< ref supported-bindings.md >}}) without making code changes. -The PostgreSQL `bindings-postgres.yaml` file included for this Quickstart contains the following: +The PostgreSQL `binding-postgres.yaml` file included for this Quickstart contains the following: ```yaml apiVersion: dapr.io/v1alpha1 @@ -487,7 +490,7 @@ Run the `csharp-quickstart-binding-sdk` service alongside a Dapr sidecar. dapr run --app-id csharp-quickstart-binding-sdk --app-port 7002 --components-path ../../../components -- dotnet run ``` -The code inside the `process_batch` function is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks like a route called via HTTP POST in your Flask application by the Dapr sidecar. +The code inside the `process_batch` function is executed every 10 seconds (defined in [`binding-cron.yaml`]({{< ref "#componentsbinding-cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks for a route called via HTTP POST in your Flask application by the Dapr sidecar. ```csharp Console.WriteLine("Processing batch.."); @@ -495,7 +498,7 @@ string jsonFile = File.ReadAllText("../../orders.json"); var ordersArray = JsonSerializer.Deserialize(jsonFile); ``` -The `csharp-quickstart-binding-sdk` service uses the PostgreSQL output binding defined in the [`bindings.yaml`]({{< ref "#bindingsyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. +The `csharp-quickstart-binding-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "#componentbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. ```csharp using var client = new DaprClientBuilder().Build(); @@ -579,18 +582,18 @@ spec: value: "@every 10s" # valid cron schedule ``` -**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding is invoked. +**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression]({{< ref cron.md >}}) that specifies how often the binding is invoked. -#### `component\bindings-postgres.yaml` component file +#### `component\binding-postgres.yaml` component file When you execute the `dapr run` command and specify the component path, the Dapr sidecar: - Initiates the PostgreSQL [binding building block]({{< ref postgres.md >}}) -- Connects to PostgreSQL using the settings specified in the `bindings-postgres.yaml` file +- Connects to PostgreSQL using the settings specified in the `binding-postgres.yaml` file -With the `bindings-postgres.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. +With the `binding-postgres.yaml` component, you can easily swap out the backend database [binding]({{< ref supported-bindings.md >}}) without making code changes. -The PostgreSQL `bindings-postgres.yaml` file included for this Quickstart contains the following: +The PostgreSQL `binding-postgres.yaml` file included for this Quickstart contains the following: ```yaml apiVersion: dapr.io/v1alpha1 @@ -681,7 +684,7 @@ Run the `go-quickstart-binding-sdk` service alongside a Dapr sidecar. dapr run --app-id go-input-binding-sdk --app-port 6002 --dapr-http-port 3502 --dapr-grpc-port 60002 --components-path ../../../components -- go run app.go ``` -The code inside the `process_batch` function is executed every 10 seconds (defined in [`cron.yaml`]({{< ref "#cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks like a route called via HTTP POST in your Flask application by the Dapr sidecar. +The code inside the `process_batch` function is executed every 10 seconds (defined in [`binding-cron.yaml`]({{< ref "#componentsbinding-cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks for a route called via HTTP POST in your Flask application by the Dapr sidecar. ```go func processCron(w http.ResponseWriter, r *http.Request) { @@ -689,7 +692,7 @@ func processCron(w http.ResponseWriter, r *http.Request) { } ``` -The `go-quickstart-binding-sdk` service uses the PostgreSQL output binding defined in the [`bindings.yaml`]({{< ref "#bindingsyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. +The `go-quickstart-binding-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "#componentbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. ```go client, err := dapr.NewClient() @@ -774,18 +777,18 @@ spec: value: "@every 10s" # valid cron schedule ``` -**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression](/reference/components-reference/supported-bindings/cron/) that specifies how often the binding is invoked. +**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression]({{< ref cron.md >}}) that specifies how often the binding is invoked. -#### `component\bindings-postgres.yaml` component file +#### `component\binding-postgres.yaml` component file When you execute the `dapr run` command and specify the component path, the Dapr sidecar: - Initiates the PostgreSQL [binding building block]({{< ref postgres.md >}}) -- Connects to PostgreSQL using the settings specified in the `bindings-postgres.yaml` file +- Connects to PostgreSQL using the settings specified in the `binding-postgres.yaml` file -With the `bindings-postgres.yaml` component, you can easily swap out the backend database [binding](/reference/components-reference/supported-bindings/) without making code changes. +With the `binding-postgres.yaml` component, you can easily swap out the backend database [binding]({{< ref supported-bindings.md >}}) without making code changes. -The PostgreSQL `bindings-postgres.yaml` file included for this Quickstart contains the following: +The PostgreSQL `binding-postgres.yaml` file included for this Quickstart contains the following: ```yaml apiVersion: dapr.io/v1alpha1 From dde188a7a1668a021d69efff361ce2541b6eb41e Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Tue, 21 Jun 2022 15:49:11 -0500 Subject: [PATCH 10/42] update go typo Signed-off-by: Hannah Hunter --- .../en/getting-started/quickstarts/bindings-quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index 8c99bb21c..56578a7de 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -678,7 +678,7 @@ Install the dependencies: go build app.go ``` -Run the `go-quickstart-binding-sdk` service alongside a Dapr sidecar. +Run the `go-input-binding-sdk` service alongside a Dapr sidecar. ```bash dapr run --app-id go-input-binding-sdk --app-port 6002 --dapr-http-port 3502 --dapr-grpc-port 60002 --components-path ../../../components -- go run app.go From 38100e5a7da6c9e615555bb73ccbb0212467a8a4 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Tue, 21 Jun 2022 17:28:56 -0500 Subject: [PATCH 11/42] change js port Signed-off-by: Hannah Hunter --- .../en/getting-started/quickstarts/bindings-quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index 56578a7de..22edc9435 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -286,7 +286,7 @@ npm install Run the `javascript-quickstart-binding-sdk` service alongside a Dapr sidecar. ```bash -dapr run --app-id javascript-quickstart-binding-sdk --app-port 5001 --dapr-http-port 3500 --components-path ../../../components -- node index.js +dapr run --app-id javascript-quickstart-binding-sdk --app-port 5002 --dapr-http-port 3500 --components-path ../../../components -- node index.js ``` The code inside the `process_batch` function is executed every 10 seconds (defined in [`binding-cron.yaml`]({{< ref "#componentsbinding-cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks for a route called via HTTP POST in your Flask application by the Dapr sidecar. From 7c11e79c6450640ad9c9092893805ddafbcf80cb Mon Sep 17 00:00:00 2001 From: greenie-msft <56556602+greenie-msft@users.noreply.github.com> Date: Tue, 21 Jun 2022 16:50:10 -0700 Subject: [PATCH 12/42] Update Preview Features List (#2555) Updated resiliency to have a version introduced and fixed version introduced for pubsub routing Signed-off-by: greenie-msft <56556602+greenie-msft@users.noreply.github.com> --- .../content/en/operations/support/support-preview-features.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/daprdocs/content/en/operations/support/support-preview-features.md b/daprdocs/content/en/operations/support/support-preview-features.md index a789b4772..68ded386c 100644 --- a/daprdocs/content/en/operations/support/support-preview-features.md +++ b/daprdocs/content/en/operations/support/support-preview-features.md @@ -16,9 +16,9 @@ For CLI there is no explicit opt-in, just the version that this was first made a | Feature | Description | Setting | Documentation | Version introduced | | ---------- |-------------|---------|---------------|-----------------| | **Partition actor reminders** | Allows actor reminders to be partitioned across multiple keys in the underlying statestore in order to improve scale and performance. | `Actor.TypeMetadata` | [How-To: Partition Actor Reminders]({{< ref "howto-actors.md#partitioning-reminders" >}}) | v1.4 | -| **Pub/Sub routing** | Allow the use of expressions to route cloud events to different URIs/paths and event handlers in your application. | `PubSub.Routing` | [How-To: Publish a message and subscribe to a topic]({{}}) | v1.7 | +| **Pub/Sub routing** | Allow the use of expressions to route cloud events to different URIs/paths and event handlers in your application. | `PubSub.Routing` | [How-To: Publish a message and subscribe to a topic]({{}}) | v1.4 | | **ARM64 Mac Support** | Dapr CLI, sidecar, and Dashboard are now natively compiled for ARM64 Macs, along with Dapr CLI installation via Homebrew. | N/A | [Install the Dapr CLI]({{}}) | v1.5 | | **--image-registry** flag with Dapr CLI| In self hosted mode you can set this flag to specify any private registry to pull the container images required to install Dapr| N/A | [init CLI command reference]({{}}) | v1.7 | -| **Resiliency** | Allows configuring of fine-grained policies for retries, timeouts and circuitbreaking. | `Resiliency` | [Configure Resiliency Policies]({{}}) | +| **Resiliency** | Allows configuring of fine-grained policies for retries, timeouts and circuitbreaking. | `Resiliency` | [Configure Resiliency Policies]({{}}) | v1.7 | | **Service invocation without default `content-type`** | When enabled removes the default service invocation content-type header value `application/json` when no content-type is provided. This will become the default behavior in release v1.9.0. This requires you to explictly set content-type headers where required for your apps. | `ServiceInvocation.NoDefaultContentType` | [Service Invocation]({{}}) | v1.7 | From 7daa1991229af31c9c67d7fbb222a0ffde0d32a4 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Wed, 22 Jun 2022 17:02:34 -0500 Subject: [PATCH 13/42] java Signed-off-by: Hannah Hunter --- .../quickstarts/bindings-quickstart.md | 213 +++++++++++++++++- 1 file changed, 212 insertions(+), 1 deletion(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index 22edc9435..ede34959d 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -17,7 +17,7 @@ In this Quickstart, you will schedule a batch script to run every 10 seconds usi Select your preferred language-specific Dapr SDK before proceeding with the Quickstart. -{{< tabs "Python" "JavaScript" ".NET" "Go" >}} +{{< tabs "Python" "JavaScript" ".NET" "Java" "Go" >}} {{% codetab %}} @@ -614,6 +614,216 @@ In the YAML file: - `spec/type` specifies that PostgreSQL is used for this binding. - `spec/metadata` defines the connection to the PostgreSQL instance used by the component. +{{% /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](https://jdk.java.net/13/) +- [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/bindings). + +```bash +git clone https://github.com/dapr/quickstarts.git +``` + +### Step 2: Run PostgreSQL Docker container locally + +Run the [PostgreSQL instance](https://www.postgresql.org/) locally in a Docker container on your machine. The Quickstart sample includes a Docker Compose file to locally customize, build, run, and initialize the `postgres` container with a default `orders` table. + +In a terminal window, from the root of the Quickstarts clone directory, navigate to the `bindings/db` directory. + +```bash +cd quickstarts/bindings/db +``` + +Run the following command to set up the container: + +```bash +docker compose up +``` + +Verify that the container is running locally. + +```bash +docker ps +``` + +The output should include: + +```bash +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +55305d1d378b postgres "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:5432->5432/tcp sql_db +``` + +### Step 3: Schedule a Cron job and write to the database + +In a new terminal window, navigate to the SDK directory. + +```bash +cd quickstarts/bindings/java/sdk/batch +``` + +Install the dependencies: + +```bash +mvn clean install +``` + +Run the `java-binding-quickstart-sdk` service alongside a Dapr sidecar. + +```bash +dapr run --app-id java-binding-quickstart-sdk --app-port 8080 --components-path ../../../components -- java -jar target/BatchProcessingService-0.0.1-SNAPSHOT.jar +``` + +The code inside the `process_batch` function is executed every 10 seconds (defined in [`binding-cron.yaml`]({{< ref "#componentsbinding-cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks for a route called via HTTP POST in your Flask application by the Dapr sidecar. + +```java +@PostMapping(path = cronBindingPath, consumes = MediaType.ALL_VALUE) +public ResponseEntity processBatch() throws IOException, Exception +``` + +The `java-binding-quickstart-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "#componentbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. + +```java +try (DaprClient client = new DaprClientBuilder().build()) { + + for (Order order : ordList.orders) { + String sqlText = String.format( + "insert into orders (orderid, customer, price) " + + "values (%s, '%s', %s);", + order.orderid, order.customer, order.price); + logger.info(sqlText); + + Map metadata = new HashMap(); + metadata.put("sql", sqlText); + + // Invoke sql output binding using Dapr SDK + client.invokeBinding(sqlBindingName, "exec", null, metadata).block(); + } + + logger.info("Finished processing batch"); + + return ResponseEntity.ok("Finished processing batch"); +} +``` + +### Step 4: View the output of the job + +Notice, as specified above, the code invokes the output binding with the `OrderId`, `Customer`, and `Price` as a payload. + +Your output binding's `print` statement output: + +``` +== APP == 2022-06-22 16:39:17.012 INFO 35772 --- [nio-8080-exec-4] c.s.c.BatchProcessingServiceController : Processing batch.. +== APP == 2022-06-22 16:39:17.268 INFO 35772 --- [nio-8080-exec-4] c.s.c.BatchProcessingServiceController : insert into orders (orderid, customer, price) values (1, 'John Smith', 100.32); +== APP == 2022-06-22 16:39:17.838 INFO 35772 --- [nio-8080-exec-4] c.s.c.BatchProcessingServiceController : insert into orders (orderid, customer, price) values (2, 'Jane Bond', 15.4); +== APP == 2022-06-22 16:39:17.844 INFO 35772 --- [nio-8080-exec-4] c.s.c.BatchProcessingServiceController : insert into orders (orderid, customer, price) values (3, 'Tony James', 35.56); +== APP == 2022-06-22 16:39:17.848 INFO 35772 --- [nio-8080-exec-4] c.s.c.BatchProcessingServiceController : Finished processing batch +``` + +In a new terminal, verify the same data has been inserted into the database. Navigate to the `bindings/db` directory. + +```bash +cd quickstarts/bindings/db +``` + +Run the following to start the interactive Postgres CLI: + +```bash +docker exec -i -t postgres psql --username postgres -p 5432 -h localhost --no-password +``` + +At the `admin=#` prompt, change to the `orders` table: + +```bash +\c orders; +``` + +At the `orders=#` prompt, select all rows: + +```bash +select * from orders; +``` + +The output should look like this: + +``` + orderid | customer | price +---------+------------+-------- + 1 | John Smith | 100.32 + 2 | Jane Bond | 15.4 + 3 | Tony James | 35.56 +``` + +#### `components\binding-cron.yaml` component file + +When you execute the `dapr run` command and specify the component path, the Dapr sidecar: + +- Initiates the Cron [binding building block]({{< ref bindings >}}) +- Calls the binding endpoint (`batch`) every 10 seconds + +The Cron `binding-cron.yaml` file included for this Quickstart contains the following: + +```yaml +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: cron + namespace: quickstarts +spec: + type: bindings.cron + version: v1 + metadata: + - name: schedule + value: "@every 10s" # valid cron schedule +``` + +**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression]({{< ref cron.md >}}) that specifies how often the binding is invoked. + +#### `component\binding-postgres.yaml` component file + +When you execute the `dapr run` command and specify the component path, the Dapr sidecar: + +- Initiates the PostgreSQL [binding building block]({{< ref postgres.md >}}) +- Connects to PostgreSQL using the settings specified in the `binding-postgres.yaml` file + +With the `binding-postgres.yaml` component, you can easily swap out the backend database [binding]({{< ref supported-bindings.md >}}) without making code changes. + +The PostgreSQL `binding-postgres.yaml` file included for this Quickstart contains the following: + +```yaml +apiVersion: dapr.io/v1alpha1 +kind: Component +metadata: + name: sqldb + namespace: quickstarts +spec: + type: bindings.postgres + version: v1 + metadata: + - name: url # Required + value: "user=postgres password=docker host=localhost port=5432 dbname=orders pool_min_conns=1 pool_max_conns=10" +``` + +In the YAML file: + +- `spec/type` specifies that PostgreSQL is used for this binding. +- `spec/metadata` defines the connection to the PostgreSQL instance used by the component. + {{% /codetab %}} @@ -825,6 +1035,7 @@ Join the discussion in our [discord channel](https://discord.gg/22ZtJrNe). - [Python](https://github.com/dapr/quickstarts/tree/master/bindings/python/http) - [JavaScript](https://github.com/dapr/quickstarts/tree/master/bindings/javascript/http) - [.NET](https://github.com/dapr/quickstarts/tree/master/bindings/csharp/http) + - [Java](https://github.com/dapr/quickstarts/tree/master/bindings/java/http) - [Go](https://github.com/dapr/quickstarts/tree/master/bindings/go/http) - Learn more about [Binding building block]({{< ref bindings >}}) From eb9af61a8406e49553c7eb457fb389c188901552 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Wed, 22 Jun 2022 17:17:48 -0500 Subject: [PATCH 14/42] move qs down in toc Signed-off-by: Hannah Hunter --- .../en/getting-started/quickstarts/bindings-quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index ede34959d..35748d807 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -2,7 +2,7 @@ type: docs title: "Quickstart: Input & Output Bindings" linkTitle: "Bindings" -weight: 70 +weight: 75 description: "Get started with Dapr's Binding building block" --- From 2a8024b91f39042ba4ceb04603e07f05fe91f3bc Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Thu, 23 Jun 2022 11:14:59 -0500 Subject: [PATCH 15/42] ignore links Signed-off-by: Hannah Hunter --- .../getting-started/quickstarts/bindings-quickstart.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index 35748d807..16cf06215 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -27,7 +27,9 @@ 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). + +- [Docker Desktop](https://www.docker.com/products/docker-desktop) + ### Step 1: Set up the environment @@ -230,7 +232,9 @@ For this example, you will need: - [Dapr CLI and initialized environment](https://docs.dapr.io/getting-started). - [Latest Node.js installed](https://nodejs.org/download/). + - [Docker Desktop](https://www.docker.com/products/docker-desktop) + ### Step 1: Set up the environment @@ -430,7 +434,9 @@ 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 @@ -835,7 +841,9 @@ 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 From 92f712d29489b587b51b0f18064f6df4416c8bcf Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Thu, 23 Jun 2022 11:46:27 -0500 Subject: [PATCH 16/42] match order of quickstarts to order of APIs in diagram Signed-off-by: Hannah Hunter --- daprdocs/content/en/getting-started/quickstarts/_index.md | 2 +- .../en/getting-started/quickstarts/bindings-quickstart.md | 2 +- .../en/getting-started/quickstarts/secrets-quickstart.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/_index.md b/daprdocs/content/en/getting-started/quickstarts/_index.md index cd4a5dff7..7202a296d 100644 --- a/daprdocs/content/en/getting-started/quickstarts/_index.md +++ b/daprdocs/content/en/getting-started/quickstarts/_index.md @@ -25,8 +25,8 @@ Hit the ground running with our Dapr quickstarts, complete with code samples aim | [Service Invocation]({{< ref serviceinvocation-quickstart.md >}}) | Call a method on another service using the service invocation API. | | [State Management]({{< ref statemanagement-quickstart.md >}}) | Create stateful applications using the state management API. | | [Publish and Subscribe]({{< ref pubsub-quickstart.md >}}) | Send and receive messages using the publish and subscribe API. | -| [Secrets Management]({{< ref secrets-quickstart.md >}}) | Retrieve secrets in the application code from a configured secret store using the secrets management API. | | [Bindings]({{< ref bindings-quickstart.md >}}) | Schedule a database insert job using the input and output bindings API. | +| [Secrets Management]({{< ref secrets-quickstart.md >}}) | Retrieve secrets in the application code from a configured secret store using the secrets management API. | | Actors | Coming soon. | | Observability | Coming soon. | | Configuration | Coming soon. | \ No newline at end of file diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index 16cf06215..2af4c0145 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -2,7 +2,7 @@ type: docs title: "Quickstart: Input & Output Bindings" linkTitle: "Bindings" -weight: 75 +weight: 74 description: "Get started with Dapr's Binding building block" --- diff --git a/daprdocs/content/en/getting-started/quickstarts/secrets-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/secrets-quickstart.md index fb02273fe..89f0da687 100644 --- a/daprdocs/content/en/getting-started/quickstarts/secrets-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/secrets-quickstart.md @@ -2,7 +2,7 @@ type: docs title: "Quickstart: Secrets Management" linkTitle: "Secrets Management" -weight: 74 +weight: 75 description: "Get started with Dapr's Secrets Management building block" --- From c8fd7189eabdec18a782ae6e434b0bca4a5b8fad Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Thu, 23 Jun 2022 12:11:18 -0500 Subject: [PATCH 17/42] carrots Signed-off-by: Hannah Hunter --- .../en/getting-started/quickstarts/bindings-quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index 2af4c0145..51c24f3d9 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -189,7 +189,7 @@ spec: value: "@every 10s" # valid cron schedule ``` -**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression]({{ ref cron.md }}) that specifies how often the binding is invoked. +**Note:** The `metadata` section of `binding-cron.yaml` contains a [Cron expression]({{< ref cron.md >}}) that specifies how often the binding is invoked. #### `component\binding-postgres.yaml` component file From 1c27f8861ff7e301a4faeaf394f6ec514dd5f9cd Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Thu, 23 Jun 2022 12:13:12 -0500 Subject: [PATCH 18/42] ignore links test Signed-off-by: Hannah Hunter --- .../en/getting-started/quickstarts/bindings-quickstart.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index 51c24f3d9..65ab320c6 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -27,8 +27,7 @@ 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) +- [Docker Desktop](https://www.docker.com/products/docker-desktop) ### Step 1: Set up the environment From ce9fd50395941becb6e23367fceb4cc16b55a44d Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Thu, 23 Jun 2022 12:15:08 -0500 Subject: [PATCH 19/42] revert Signed-off-by: Hannah Hunter --- .../en/getting-started/quickstarts/bindings-quickstart.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index 65ab320c6..6fb9ff32c 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -27,7 +27,8 @@ 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) + +- [Docker Desktop](https://www.docker.com/products/docker-desktop) ### Step 1: Set up the environment From dcd5b7d55a745b2934d30a3567767910d0426ba4 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Thu, 23 Jun 2022 16:41:09 -0500 Subject: [PATCH 20/42] change app name Signed-off-by: Hannah Hunter --- .../quickstarts/bindings-quickstart.md | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index 6fb9ff32c..5d414bc65 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -82,10 +82,10 @@ Install the dependencies: pip3 install -r requirements.txt ``` -Run the `python-binding-quickstart-sdk` service alongside a Dapr sidecar. +Run the `batch-sdk` service alongside a Dapr sidecar. ```bash -dapr run --app-id python-binding-quickstart-sdk --app-port 50051 --components-path ../../../components -- python3 app.py +dapr run --app-id batch-sdk --app-port 50051 --components-path ../../../components -- python3 app.py ``` The code inside the `process_batch` function is executed every 10 seconds (defined in [`binding-cron.yaml`]({{< ref "#componentsbinding-cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks for a route called via HTTP POST in your Flask application by the Dapr sidecar. @@ -96,7 +96,7 @@ The code inside the `process_batch` function is executed every 10 seconds (defin def process_batch(): ``` -The `python-binding-quickstart-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "#componentbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. +The `batch-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "#componentbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. ```python with DaprClient() as d: @@ -287,10 +287,10 @@ Install the dependencies: npm install ``` -Run the `javascript-quickstart-binding-sdk` service alongside a Dapr sidecar. +Run the `batch-sdk` service alongside a Dapr sidecar. ```bash -dapr run --app-id javascript-quickstart-binding-sdk --app-port 5002 --dapr-http-port 3500 --components-path ../../../components -- node index.js +dapr run --app-id batch-sdk --app-port 5002 --dapr-http-port 3500 --components-path ../../../components -- node index.js ``` The code inside the `process_batch` function is executed every 10 seconds (defined in [`binding-cron.yaml`]({{< ref "#componentsbinding-cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks for a route called via HTTP POST in your Flask application by the Dapr sidecar. @@ -302,7 +302,7 @@ async function start() { } ``` -The `javascript-quickstart-binding-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "##componentsbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. +The `batch-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "##componentsbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. ```javascript async function processBatch(){ @@ -490,10 +490,10 @@ dotnet restore dotnet build batch.csproj ``` -Run the `csharp-quickstart-binding-sdk` service alongside a Dapr sidecar. +Run the `batch-sdk` service alongside a Dapr sidecar. ```bash -dapr run --app-id csharp-quickstart-binding-sdk --app-port 7002 --components-path ../../../components -- dotnet run +dapr run --app-id batch-sdk --app-port 7002 --components-path ../../../components -- dotnet run ``` The code inside the `process_batch` function is executed every 10 seconds (defined in [`binding-cron.yaml`]({{< ref "#componentsbinding-cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks for a route called via HTTP POST in your Flask application by the Dapr sidecar. @@ -504,7 +504,7 @@ string jsonFile = File.ReadAllText("../../orders.json"); var ordersArray = JsonSerializer.Deserialize(jsonFile); ``` -The `csharp-quickstart-binding-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "#componentbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. +The `batch-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "#componentbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. ```csharp using var client = new DaprClientBuilder().Build(); @@ -689,10 +689,10 @@ Install the dependencies: mvn clean install ``` -Run the `java-binding-quickstart-sdk` service alongside a Dapr sidecar. +Run the `batch-sdk` service alongside a Dapr sidecar. ```bash -dapr run --app-id java-binding-quickstart-sdk --app-port 8080 --components-path ../../../components -- java -jar target/BatchProcessingService-0.0.1-SNAPSHOT.jar +dapr run --app-id batch-sdk --app-port 8080 --components-path ../../../components -- java -jar target/BatchProcessingService-0.0.1-SNAPSHOT.jar ``` The code inside the `process_batch` function is executed every 10 seconds (defined in [`binding-cron.yaml`]({{< ref "#componentsbinding-cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks for a route called via HTTP POST in your Flask application by the Dapr sidecar. @@ -702,7 +702,7 @@ The code inside the `process_batch` function is executed every 10 seconds (defin public ResponseEntity processBatch() throws IOException, Exception ``` -The `java-binding-quickstart-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "#componentbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. +The `batch-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "#componentbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. ```java try (DaprClient client = new DaprClientBuilder().build()) { @@ -896,10 +896,10 @@ Install the dependencies: go build app.go ``` -Run the `go-input-binding-sdk` service alongside a Dapr sidecar. +Run the `batch-sdk` service alongside a Dapr sidecar. ```bash -dapr run --app-id go-input-binding-sdk --app-port 6002 --dapr-http-port 3502 --dapr-grpc-port 60002 --components-path ../../../components -- go run app.go +dapr run --app-id batch-sdk --app-port 6002 --dapr-http-port 3502 --dapr-grpc-port 60002 --components-path ../../../components -- go run app.go ``` The code inside the `process_batch` function is executed every 10 seconds (defined in [`binding-cron.yaml`]({{< ref "#componentsbinding-cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks for a route called via HTTP POST in your Flask application by the Dapr sidecar. @@ -910,7 +910,7 @@ func processCron(w http.ResponseWriter, r *http.Request) { } ``` -The `go-quickstart-binding-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "#componentbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. +The `batch-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "#componentbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. ```go client, err := dapr.NewClient() From 68d2a6b103dea621f7327cd73953bad6cfb7cbff Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Thu, 23 Jun 2022 17:50:06 -0500 Subject: [PATCH 21/42] add back python example Signed-off-by: Hannah Hunter --- .../howto-manage-configuration.md | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) 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 524d54dfd..d08f0bb44 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 @@ -212,7 +212,40 @@ message SubscribeConfigurationRequest { } ``` -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](https://grpc.io/docs/languages/) for usage. +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. + +Below are the examples in sdks: + +{{< tabs Python>}} + +{{% codetab %}} +```python +#dependencies +import asyncio +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()) +``` + +```bash +dapr run --app-id orderprocessing --components-path components/ -- python3 OrderProcessingService.py +``` + +{{% /codetab %}} + +{{< /tabs >}} #### Stop watching configuration items From 2c7b213fcfe60ee28dfc7d5feb61b785cdc92644 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Thu, 23 Jun 2022 17:58:04 -0500 Subject: [PATCH 22/42] fix link Signed-off-by: Hannah Hunter --- .../content/en/getting-started/quickstarts/pubsub-quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/pubsub-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/pubsub-quickstart.md index d7e25abbe..86e1fa033 100644 --- a/daprdocs/content/en/getting-started/quickstarts/pubsub-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/pubsub-quickstart.md @@ -508,7 +508,7 @@ 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](https://jdk.java.net/13/) + - [OpenJDK](https://jdk.java.net/projects/jdk/13/) - [Apache Maven](https://maven.apache.org/install.html), version 3.x. - [Docker Desktop](https://www.docker.com/products/docker-desktop) From 2d8afa7505a91963b2c6c2bd1e122b39afb8f902 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Thu, 23 Jun 2022 18:00:27 -0500 Subject: [PATCH 23/42] fix links Signed-off-by: Hannah Hunter --- .../en/getting-started/quickstarts/secrets-quickstart.md | 2 +- .../getting-started/quickstarts/serviceinvocation-quickstart.md | 2 +- .../getting-started/quickstarts/statemanagement-quickstart.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/secrets-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/secrets-quickstart.md index fb02273fe..46c714ef5 100644 --- a/daprdocs/content/en/getting-started/quickstarts/secrets-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/secrets-quickstart.md @@ -352,7 +352,7 @@ 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](https://jdk.java.net/13/) + - [OpenJDK](https://jdk.java.net/projects/jdk/13/) - [Apache Maven](https://maven.apache.org/install.html), version 3.x. - [Docker Desktop](https://www.docker.com/products/docker-desktop) diff --git a/daprdocs/content/en/getting-started/quickstarts/serviceinvocation-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/serviceinvocation-quickstart.md index af2066c16..8399a0603 100644 --- a/daprdocs/content/en/getting-started/quickstarts/serviceinvocation-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/serviceinvocation-quickstart.md @@ -388,7 +388,7 @@ 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](https://jdk.java.net/13/) + - [OpenJDK](https://jdk.java.net/projects/jdk/13/) - [Apache Maven](https://maven.apache.org/install.html), version 3.x. - [Docker Desktop](https://www.docker.com/products/docker-desktop) diff --git a/daprdocs/content/en/getting-started/quickstarts/statemanagement-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/statemanagement-quickstart.md index b605bf3f0..928390ad4 100644 --- a/daprdocs/content/en/getting-started/quickstarts/statemanagement-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/statemanagement-quickstart.md @@ -386,7 +386,7 @@ 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](https://jdk.java.net/13/) + - [OpenJDK](https://jdk.java.net/projects/jdk/13/) - [Apache Maven](https://maven.apache.org/install.html), version 3.x. - [Docker Desktop](https://www.docker.com/products/docker-desktop) From 0439aeda526889c14ade169ad5eddcd8c47be1b4 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Thu, 23 Jun 2022 19:02:48 -0500 Subject: [PATCH 24/42] image Signed-off-by: Hannah Hunter --- .../bindings-quickstart.png | Bin 23076 -> 47254 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/daprdocs/static/images/bindings-quickstart/bindings-quickstart.png b/daprdocs/static/images/bindings-quickstart/bindings-quickstart.png index 842ad2387991aa6cd7123b69ab0260e3484ee7de..1ba3808a213bd2996582de56796eefc030718f55 100644 GIT binary patch literal 47254 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 CD8?QD From 0082b87912966806db2d1bfd08e9e370118ba5c9 Mon Sep 17 00:00:00 2001 From: Piotr Date: Thu, 23 Jun 2022 23:19:33 -0400 Subject: [PATCH 25/42] Update description.html (#2563) Fixing broken links Signed-off-by: Piotr Co-authored-by: greenie-msft <56556602+greenie-msft@users.noreply.github.com> --- daprdocs/layouts/partials/components/description.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/daprdocs/layouts/partials/components/description.html b/daprdocs/layouts/partials/components/description.html index 449bcf55a..7cc5a1bf6 100644 --- a/daprdocs/layouts/partials/components/description.html +++ b/daprdocs/layouts/partials/components/description.html @@ -1,16 +1,16 @@

Table captions:

-

Status: Component +

Status: Component certification status

Since: defines from which Dapr Runtime version, the component is in the current status

Component version: defines the version of the component

-
\ No newline at end of file + From f88c853c4ef728053cfb63700fe29c950f56021d Mon Sep 17 00:00:00 2001 From: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> Date: Fri, 24 Jun 2022 13:37:42 -0500 Subject: [PATCH 26/42] [Bindings] Address issue; general freshness (#2543) * address issue and general freshness pass Signed-off-by: Hannah Hunter * link to bindings api and update table Signed-off-by: Hannah Hunter Co-authored-by: Mark Fussell --- .../bindings/bindings-overview.md | 49 +++++++++++-------- .../content/en/reference/api/bindings_api.md | 2 +- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/daprdocs/content/en/developing-applications/building-blocks/bindings/bindings-overview.md b/daprdocs/content/en/developing-applications/building-blocks/bindings/bindings-overview.md index d82d3d2aa..a2a229425 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/bindings/bindings-overview.md +++ b/daprdocs/content/en/developing-applications/building-blocks/bindings/bindings-overview.md @@ -6,49 +6,56 @@ weight: 100 description: Overview of the bindings API building block --- -## Introduction +Using Dapr's bindings API, you can both trigger your app with events coming in from external systems and interface with external systems. In addition, the Dapr binding API enables you to: -Using bindings, you can trigger your app with events coming in from external systems, or interface with external systems. This building block provides several benefits for you and your code: - -- Remove the complexities of connecting to, and polling from, messaging systems such as queues and message buses -- Focus on business logic and not implementation details of how to interact with a system +- Remove the complexities of connecting to and polling from messaging systems, such as queues and message buses +- Focus on business logic, instead of the implementation details of how to interact with a system - Keep your code free from SDKs or libraries - Handle retries and failure recovery - Switch between bindings at run time -- Build portable applications where environment-specific bindings are set-up and no code changes are required +- Build portable applications with environment-specific bindings set up and no code changes required -For a specific example, bindings would allow your microservice to respond to incoming Twilio/SMS messages without adding or configuring a third-party Twilio SDK, worrying about polling from Twilio (or using websockets, etc.). +For example, with bindings, your microservice can respond to incoming Twilio/SMS messages without: -Bindings are developed independently of Dapr runtime. You can view and contribute to the bindings [here](https://github.com/dapr/components-contrib/tree/master/bindings). +- Adding or configuring a third-party Twilio SDK +- Worrying about polling from Twilio (or using websockets, etc.) + +{{% alert title="Note" color="primary" %}} + Bindings are developed independently of Dapr runtime. You can [view and contribute to the bindings](https://github.com/dapr/components-contrib/tree/master/bindings). + +{{% /alert %}} ## Input bindings -Input bindings are used to trigger your application when an event from an external resource has occurred. -An optional payload and metadata may be sent with the request. +With input bindings, you can trigger your application when an event from an external resource has occurred. An optional payload and metadata may be sent with the request. In order to receive events from an input binding: -1. Define the component YAML that describes the type of binding and its metadata (connection info, etc.) -2. Listen on an HTTP endpoint for the incoming event, or use the gRPC proto library to get incoming events +1. Define the component YAML that describes the type of binding and its metadata (connection info, etc.). +2. Listen on an HTTP endpoint for the incoming event, or use the gRPC proto library to get incoming events. -> On startup Dapr sends a `OPTIONS` request for all defined input bindings to the application and expects a status code other than `NOT FOUND (404)` if this application wants to subscribe to the binding. +{{% alert title="Note" color="primary" %}} + On startup, Dapr sends [an OPTIONS request]({{< ref "bindings_api.md#invoking-service-code-through-input-bindings" >}}) for all defined input bindings to the application and expects a status code 2xx or 405 if this application wants to subscribe to the binding. + +{{% /alert %}} Read the [Create an event-driven app using input bindings]({{< ref howto-triggers.md >}}) page to get started with input bindings. ## Output bindings -Output bindings allow you to invoke external resources. An optional payload and metadata can be sent with the invocation request. +With output bindings, you can invoke external resources. An optional payload and metadata can be sent with the invocation request. In order to invoke an output binding: -1. Define the component YAML that describes the type of binding and its metadata (connection info, etc.) -2. Use the HTTP endpoint or gRPC method to invoke the binding with an optional payload +1. Define the component YAML that describes the type of binding and its metadata (connection info, etc.). +2. Use the HTTP endpoint or gRPC method to invoke the binding with an optional payload. Read the [Use output bindings to interface with external resources]({{< ref howto-bindings.md >}}) page to get started with output bindings. ## Next Steps -* Follow these guides on: - * [How-To: Trigger a service from different resources with input bindings]({{< ref howto-triggers.md >}}) - * [How-To: Use output bindings to interface with external resources]({{< ref howto-bindings.md >}}) -* Try out the [bindings quickstart](https://github.com/dapr/quickstarts/tree/master/tutorials/bindings/README.md) which shows how to bind to a Kafka queue -* Read the [bindings API specification]({{< ref bindings_api.md >}}) + +- Follow these guides on: + - [How-To: Trigger a service from different resources with input bindings]({{< ref howto-triggers.md >}}) + - [How-To: Use output bindings to interface with external resources]({{< ref howto-bindings.md >}}) +- Try out the [bindings tutorial](https://github.com/dapr/quickstarts/tree/master/tutorials/bindings/README.md) to experiment with binding to a Kafka queue. +- Read the [bindings API specification]({{< ref bindings_api.md >}}) diff --git a/daprdocs/content/en/reference/api/bindings_api.md b/daprdocs/content/en/reference/api/bindings_api.md index 1f13c857e..4d9476504 100644 --- a/daprdocs/content/en/reference/api/bindings_api.md +++ b/daprdocs/content/en/reference/api/bindings_api.md @@ -99,7 +99,7 @@ OPTIONS http://localhost:/ Code | Description ---- | ----------- 404 | Application does not want to bind to the binding -all others | Application wants to bind to the binding +2xx or 405 | Application wants to bind to the binding #### URL Parameters From b00ce0371e3a21b6189c100c610591451f87c876 Mon Sep 17 00:00:00 2001 From: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> Date: Fri, 24 Jun 2022 14:37:55 -0500 Subject: [PATCH 27/42] [Pub/sub subscriptions] Fix C# example (#2545) * fix csharp example per hal Signed-off-by: Hannah Hunter * update per Mark Signed-off-by: Hannah Hunter * add second example Signed-off-by: Hannah Hunter Co-authored-by: Mark Fussell --- .../pubsub/subscription-methods.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/daprdocs/content/en/developing-applications/building-blocks/pubsub/subscription-methods.md b/daprdocs/content/en/developing-applications/building-blocks/pubsub/subscription-methods.md index e34a9dd8a..b963d13da 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/pubsub/subscription-methods.md +++ b/daprdocs/content/en/developing-applications/building-blocks/pubsub/subscription-methods.md @@ -191,15 +191,25 @@ The programmatic approach returns the `routes` JSON structure within the code, u {{% codetab %}} ```csharp -[Topic("pubsub", "checkout", event.type ==\"order\"")] -[HttpPost("orders")] -public async Task> HandleCheckout(Checkout checkout, [FromServices] DaprClient daprClient) +[Topic("pubsub", "orders")] +[HttpPost("/checkout")] +public async Task>Checkout(Order order, [FromServices] DaprClient daprClient) { // Logic - return stock; + return order; } ``` +or + +```csharp +// Dapr subscription in [Topic] routes orders topic to this route +app.MapPost("/checkout", [Topic("pubsub", "orders")] (Order order) => { + Console.WriteLine("Subscriber received : " + order); + return Results.Ok(order); +}); +``` + {{% /codetab %}} {{% codetab %}} From f88533b0f962fd2ff42e744a2e348b5098ce107c Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Fri, 24 Jun 2022 16:30:35 -0500 Subject: [PATCH 28/42] update image Signed-off-by: Hannah Hunter --- .../bindings-quickstart.png | Bin 47254 -> 48513 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/daprdocs/static/images/bindings-quickstart/bindings-quickstart.png b/daprdocs/static/images/bindings-quickstart/bindings-quickstart.png index 1ba3808a213bd2996582de56796eefc030718f55..c10bbd38eee7ba5d519047a2e2526bb5ba0b218c 100644 GIT binary patch literal 48513 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 E4@g3&Bme*a literal 47254 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 Date: Fri, 24 Jun 2022 17:02:30 -0500 Subject: [PATCH 29/42] [kafka] updates to bindings and pubsub component docs (#2552) * add updates for kafka bindings and pubsub Signed-off-by: Hannah Hunter * add suggestion from sky Signed-off-by: Hannah Hunter * reference authentication from pubsub Signed-off-by: Hannah Hunter * add Mark suggestion Signed-off-by: Hannah Hunter Co-authored-by: Mark Fussell --- .../supported-bindings/kafka.md | 14 ++++++++-- .../supported-pubsub/setup-apache-kafka.md | 27 ++++++++++--------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/daprdocs/content/en/reference/components-reference/supported-bindings/kafka.md b/daprdocs/content/en/reference/components-reference/supported-bindings/kafka.md index 67221c423..f9c75406d 100644 --- a/daprdocs/content/en/reference/components-reference/supported-bindings/kafka.md +++ b/daprdocs/content/en/reference/components-reference/supported-bindings/kafka.md @@ -51,14 +51,20 @@ spec: |--------------------|:--------:|------------|-----|---------| | topics | N | Input | A comma-separated string of topics. | `"mytopic1,topic2"` | | brokers | Y | Input/Output | A comma-separated string of Kafka brokers. | `"localhost:9092,dapr-kafka.myapp.svc.cluster.local:9093"` | +| clientID | N | Input/Output | A user-provided string sent with every request to the Kafka brokers for logging, debugging, and auditing purposes. | `"my-dapr-app"` | | consumerGroup | N | Input | A kafka consumer group to listen on. Each record published to a topic is delivered to one consumer within each consumer group subscribed to the topic. | `"group1"` | +| consumeRetryEnabled | N | Input/Output | Enable consume retry by setting to `"true"`. Default to `false` in Kafka binding component. | `"true"`, `"false"` | | publishTopic | Y | Output | The topic to publish to. | `"mytopic"` | -| authRequired | Y | Input/Output | Enable [SASL](https://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer) authentication with the Kafka brokers. | `"true"`, `"false"` | +| authRequired | N | *Deprecated* | Enable [SASL](https://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer) authentication with the Kafka brokers. | `"true"`, `"false"` | +| authType | Y | Input/Output | Configure or disable authentication. Supported values: `none`, `password`, `mtls`, or `oidc` | `"password"`, `"none"` | | saslUsername | N | Input/Output | The SASL username used for authentication. Only required if `authRequired` is set to `"true"`. | `"adminuser"` | | saslPassword | N | Input/Output | The SASL password used for authentication. Can be `secretKeyRef` to use a [secret reference]({{< ref component-secrets.md >}}). Only required if `authRequired` is set to `"true"`. | `""`, `"KeFg23!"` | | initialOffset | N | Input | The initial offset to use if no offset was previously committed. Should be "newest" or "oldest". Defaults to "newest". | `"oldest"` | | maxMessageBytes | N | Input/Output | The maximum size in bytes allowed for a single Kafka message. Defaults to 1024. | `2048` | -| version | N | Input/Output | Kafka cluster version. Defaults to 1.0.0 | `1.0.0` +| oidcTokenEndpoint | N | Input/Output | Full URL to an OAuth2 identity provider access token endpoint. Required when `authType` is set to `oidc` | "https://identity.example.com/v1/token" | +| oidcClientID | N | Input/Output | The OAuth2 client ID that has been provisioned in the identity provider. Required when `authType` is set to `oidc` | `dapr-kafka` | +| oidcClientSecret | N | Input/Output | The OAuth2 client secret that has been provisioned in the identity provider: Required when `authType` is set to `oidc` | `"KeFg23!"` | +| oidcScopes | N | Input/Output | Comma-delimited list of OAuth2/OIDC scopes to request with the access token. Recommended when `authType` is set to `oidc`. Defaults to `"openid"` | `"openid,kafka-prod"` | ## Binding support @@ -68,6 +74,10 @@ This component supports **output binding** with the following operations: - `create` +## Authentication + +Kafka supports a variety of authentication schemes and Dapr supports several: SASL password, mTLS, OIDC/OAuth2. [Learn more about Kafka's authentication method for both the Kafka binding and Kafka pub/sub components]({{< ref "setup-apache-kafka.md#authentication" >}}). + ## Specifying a partition key When invoking the Kafka binding, its possible to provide an optional partition key by using the `metadata` section in the request body. diff --git a/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-apache-kafka.md b/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-apache-kafka.md index 7c0c0ddaa..034c87279 100644 --- a/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-apache-kafka.md +++ b/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-apache-kafka.md @@ -58,18 +58,18 @@ spec: | saslPassword | N | The SASL password used for authentication. Can be `secretKeyRef` to use a [secret reference]({{< ref component-secrets.md >}}). Only required if `authType is set to `"password"`. | `""`, `"KeFg23!"` | initialOffset | N | The initial offset to use if no offset was previously committed. Should be "newest" or "oldest". Defaults to "newest". | `"oldest"` | maxMessageBytes | N | The maximum size in bytes allowed for a single Kafka message. Defaults to 1024. | `2048` -| consumeRetryInterval | N | The interval between retries when attempting to consume topics. Treats numbers without suffix as milliseconds. Defaults to 100ms. | `200ms` -| version | N | Kafka cluster version. Defaults to 2.0.0.0 | `0.10.2.0` +| consumeRetryInterval | N | The interval between retries when attempting to consume topics. Treats numbers without suffix as milliseconds. Defaults to 100ms. | `200ms` | +| consumeRetryEnabled | N | Disable consume retry by setting `"false"` | `"true"`, `"false"` | +| version | N | Kafka cluster version. Defaults to 2.0.0.0 | `0.10.2.0` | | caCert | N | Certificate authority certificate, required for using TLS. Can be `secretKeyRef` to use a secret reference | `"-----BEGIN CERTIFICATE-----\n\n-----END CERTIFICATE-----"` | clientCert | N | Client certificate, required for `authType` `mtls`. Can be `secretKeyRef` to use a secret reference | `"-----BEGIN CERTIFICATE-----\n\n-----END CERTIFICATE-----"` | clientKey | N | Client key, required for `authType` `mtls` Can be `secretKeyRef` to use a secret reference | `"-----BEGIN RSA PRIVATE KEY-----\n\n-----END RSA PRIVATE KEY-----"` | skipVerify | N | Skip TLS verification, this is not recommended for use in production. Defaults to `"false"` | `"true"`, `"false"` | -| disableTls | N | Disable TLS for transport security. This is not recommended for use in production. Defaults to `"false"` | `"true"`, `"false"` | +| disableTls | N | Disable TLS for transport security. To disable, you're not required to set value to `"true"`. This is not recommended for use in production. Defaults to `"false"`. | `"true"`, `"false"` | | oidcTokenEndpoint | N | Full URL to an OAuth2 identity provider access token endpoint. Required when `authType` is set to `oidc` | "https://identity.example.com/v1/token" | -| oidcClientID | N | The OAuth2 client ID that has been provisioned in the identity provider. Required when `authType is set to `oidc` | `dapr-kafka` | +| oidcClientID | N | The OAuth2 client ID that has been provisioned in the identity provider. Required when `authType` is set to `oidc` | `dapr-kafka` | | oidcClientSecret | N | The OAuth2 client secret that has been provisioned in the identity provider: Required when `authType` is set to `oidc` | `"KeFg23!"` | -| oidcScopes | N | Comma-delimited list of OAuth2/OIDC scopes to request with the access token. Recommended when `authType` is set to `oidc`. Defaults to `"openid"` | '"openid,kafka-prod"` | - +| oidcScopes | N | Comma-delimited list of OAuth2/OIDC scopes to request with the access token. Recommended when `authType` is set to `oidc`. Defaults to `"openid"` | `"openid,kafka-prod"` | The `secretKeyRef` above is referencing a [kubernetes secrets store]({{< ref kubernetes-secret-store.md >}}) to access the tls information. Visit [here]({{< ref setup-secret-store.md >}}) to learn more about how to configure a secret store component. @@ -198,12 +198,15 @@ spec: #### OAuth2 or OpenID Connect -Setting `authType` to `oidc` enables SASL authentication via the **OAUTHBEARER** mechanism. This supports specifying a bearer -token from an external OAuth2 or [OIDC](https://en.wikipedia.org/wiki/OpenID) identity provider. Currenly only the **client_credentials** grant is supported. Configure `oidcTokenEndpoint` to -the full URL for the identity provider access token endpoint. Set `oidcClientID` and `oidcClientSecret` to the client credentials provisioned in the identity provider. If `caCert` -is specified in the component configuration, the certificate is appended to the system CA trust for verifying the identity provider certificate. Similarly, if `skipVerify` -is specified in the component configuration, verification will also be skipped when accessing the identity provider. By default, the only scope requested for the token is `openid`; it is **highly** recommended -that additional scopes be specified via `oidcScopes` in a comma-separated list and validated by the Kafka broker. If additional scopes are not used to narrow the validity of the access token, +Setting `authType` to `oidc` enables SASL authentication via the **OAUTHBEARER** mechanism. This supports specifying a bearer token from an external OAuth2 or [OIDC](https://en.wikipedia.org/wiki/OpenID) identity provider. Currently, only the **client_credentials** grant is supported. + +Configure `oidcTokenEndpoint` to the full URL for the identity provider access token endpoint. + +Set `oidcClientID` and `oidcClientSecret` to the client credentials provisioned in the identity provider. + +If `caCert` is specified in the component configuration, the certificate is appended to the system CA trust for verifying the identity provider certificate. Similarly, if `skipVerify` is specified in the component configuration, verification will also be skipped when accessing the identity provider. + +By default, the only scope requested for the token is `openid`; it is **highly** recommended that additional scopes be specified via `oidcScopes` in a comma-separated list and validated by the Kafka broker. If additional scopes are not used to narrow the validity of the access token, a compromised Kafka broker could replay the token to access other services as the Dapr clientID. ```yaml From 7e53395b4a6de120a156fd102395284c05c38810 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Fri, 24 Jun 2022 17:12:58 -0500 Subject: [PATCH 30/42] remove faulty link Signed-off-by: Hannah Hunter --- .../en/getting-started/quickstarts/bindings-quickstart.md | 2 +- .../content/en/getting-started/quickstarts/pubsub-quickstart.md | 2 +- .../en/getting-started/quickstarts/secrets-quickstart.md | 2 +- .../getting-started/quickstarts/serviceinvocation-quickstart.md | 2 +- .../getting-started/quickstarts/statemanagement-quickstart.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index 5d414bc65..65d87d993 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -632,7 +632,7 @@ 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](https://jdk.java.net/13/) + - OpenJDK - [Apache Maven](https://maven.apache.org/install.html), version 3.x. - [Docker Desktop](https://www.docker.com/products/docker-desktop) diff --git a/daprdocs/content/en/getting-started/quickstarts/pubsub-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/pubsub-quickstart.md index 86e1fa033..72ca69f51 100644 --- a/daprdocs/content/en/getting-started/quickstarts/pubsub-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/pubsub-quickstart.md @@ -508,7 +508,7 @@ 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](https://jdk.java.net/projects/jdk/13/) + - OpenJDK - [Apache Maven](https://maven.apache.org/install.html), version 3.x. - [Docker Desktop](https://www.docker.com/products/docker-desktop) diff --git a/daprdocs/content/en/getting-started/quickstarts/secrets-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/secrets-quickstart.md index fe5067486..26509bf81 100644 --- a/daprdocs/content/en/getting-started/quickstarts/secrets-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/secrets-quickstart.md @@ -352,7 +352,7 @@ 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](https://jdk.java.net/projects/jdk/13/) + - OpenJDK - [Apache Maven](https://maven.apache.org/install.html), version 3.x. - [Docker Desktop](https://www.docker.com/products/docker-desktop) diff --git a/daprdocs/content/en/getting-started/quickstarts/serviceinvocation-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/serviceinvocation-quickstart.md index 8399a0603..57e786ec8 100644 --- a/daprdocs/content/en/getting-started/quickstarts/serviceinvocation-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/serviceinvocation-quickstart.md @@ -388,7 +388,7 @@ 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](https://jdk.java.net/projects/jdk/13/) + - OpenJDK - [Apache Maven](https://maven.apache.org/install.html), version 3.x. - [Docker Desktop](https://www.docker.com/products/docker-desktop) diff --git a/daprdocs/content/en/getting-started/quickstarts/statemanagement-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/statemanagement-quickstart.md index 928390ad4..cfebf25e5 100644 --- a/daprdocs/content/en/getting-started/quickstarts/statemanagement-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/statemanagement-quickstart.md @@ -386,7 +386,7 @@ 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](https://jdk.java.net/projects/jdk/13/) + - OpenJDK - [Apache Maven](https://maven.apache.org/install.html), version 3.x. - [Docker Desktop](https://www.docker.com/products/docker-desktop) From 9b22bc468fc7811b1fc15b878531184c995f388b Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Mon, 27 Jun 2022 15:20:59 -0500 Subject: [PATCH 31/42] updates to quickstart code snippets and cross-linking Signed-off-by: Hannah Hunter --- .../building-blocks/secrets/howto-secrets.md | 5 ++ .../howto-invoke-discover-services.md | 5 +- .../en/getting-started/quickstarts/_index.md | 10 +-- .../quickstarts/bindings-quickstart.md | 67 ++++++++----------- 4 files changed, 43 insertions(+), 44 deletions(-) diff --git a/daprdocs/content/en/developing-applications/building-blocks/secrets/howto-secrets.md b/daprdocs/content/en/developing-applications/building-blocks/secrets/howto-secrets.md index 8630094a6..960a4aa5b 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/secrets/howto-secrets.md +++ b/daprdocs/content/en/developing-applications/building-blocks/secrets/howto-secrets.md @@ -10,6 +10,11 @@ This guide demonstrates how to use Dapr's secrets API in your code to leverage t Diagram showing secrets management of example service +{{% alert title="Note" color="primary" %}} + If you haven't already, [try out the secrets management quickstart]({{< ref secrets-quickstart.md >}}) for a quick walk-through on how to use the secrets API. + +{{% /alert %}} + ## Set up a secret store Before retrieving secrets in your application's code, you must configure a secret store component. This example configures a local secret store which uses a local JSON file to store secrets. diff --git a/daprdocs/content/en/developing-applications/building-blocks/service-invocation/howto-invoke-discover-services.md b/daprdocs/content/en/developing-applications/building-blocks/service-invocation/howto-invoke-discover-services.md index 2af48cbf3..453e85113 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/service-invocation/howto-invoke-discover-services.md +++ b/daprdocs/content/en/developing-applications/building-blocks/service-invocation/howto-invoke-discover-services.md @@ -10,7 +10,10 @@ This article demonstrates how to deploy services each with an unique application Diagram showing service invocation of example service -For a complete sample demonstrating service invocation, [walk through the service invocation quickstart](https://github.com/dapr/quickstarts/tree/master/service_invocation). +{{% alert title="Note" color="primary" %}} + If you haven't already, [try out the service invocation quickstart]({{< ref serviceinvocation-quickstart.md >}}) for a quick walk-through on how to use the service invocation API. + +{{% /alert %}} ## Choose an ID for your service diff --git a/daprdocs/content/en/getting-started/quickstarts/_index.md b/daprdocs/content/en/getting-started/quickstarts/_index.md index 7202a296d..dfd2d2d26 100644 --- a/daprdocs/content/en/getting-started/quickstarts/_index.md +++ b/daprdocs/content/en/getting-started/quickstarts/_index.md @@ -22,11 +22,11 @@ Hit the ground running with our Dapr quickstarts, complete with code samples aim | Quickstarts | Description | | ----------- | ----------- | -| [Service Invocation]({{< ref serviceinvocation-quickstart.md >}}) | Call a method on another service using the service invocation API. | -| [State Management]({{< ref statemanagement-quickstart.md >}}) | Create stateful applications using the state management API. | -| [Publish and Subscribe]({{< ref pubsub-quickstart.md >}}) | Send and receive messages using the publish and subscribe API. | -| [Bindings]({{< ref bindings-quickstart.md >}}) | Schedule a database insert job using the input and output bindings API. | -| [Secrets Management]({{< ref secrets-quickstart.md >}}) | Retrieve secrets in the application code from a configured secret store using the secrets management API. | +| [Publish and Subscribe]({{< ref pubsub-quickstart.md >}}) | Asynchronous communication between two services using messaging. | +| [Service Invocation]({{< ref serviceinvocation-quickstart.md >}}) | Asynchronous communication between two services using HTTP. | +| [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. | | Actors | Coming soon. | | Observability | Coming soon. | | Configuration | Coming soon. | \ No newline at end of file diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index 65d87d993..7092dd2e0 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -99,23 +99,11 @@ def process_batch(): The `batch-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "#componentbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. ```python -with DaprClient() as d: - sqlCmd = ('insert into orders (orderid, customer, price) values' + - '(%s, \'%s\', %s)' % (order_line['orderid'], - order_line['customer'], - order_line['price'])) - payload = {'sql': sqlCmd} - - print(sqlCmd, flush=True) - - try: - # Insert order using Dapr output binding via HTTP Post - resp = d.invoke_binding(binding_name=sql_binding, operation='exec', - binding_metadata=payload, data='') - return resp - except Exception as e: - print(e, flush=True) - raise SystemExit(e) +try: + # Insert order using Dapr output binding via HTTP Post + resp = d.invoke_binding(binding_name=sql_binding, operation='exec', + binding_metadata=payload, data='') + return resp ``` ### Step 4: View the output of the job @@ -499,15 +487,12 @@ dapr run --app-id batch-sdk --app-port 7002 --components-path ../../../component The code inside the `process_batch` function is executed every 10 seconds (defined in [`binding-cron.yaml`]({{< ref "#componentsbinding-cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks for a route called via HTTP POST in your Flask application by the Dapr sidecar. ```csharp -Console.WriteLine("Processing batch.."); -string jsonFile = File.ReadAllText("../../orders.json"); -var ordersArray = JsonSerializer.Deserialize(jsonFile); -``` +app.MapPost("/" + cronBindingName, async () => { -The `batch-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "#componentbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. - -```csharp -using var client = new DaprClientBuilder().Build(); + Console.WriteLine("Processing batch.."); + string jsonFile = File.ReadAllText("../../../orders.json"); + var ordersArray = JsonSerializer.Deserialize(jsonFile); + using var client = new DaprClientBuilder().Build(); foreach(Order ord in ordersArray?.orders ?? new Order[] {}){ var sqlText = $"insert into orders (orderid, customer, price) values ({ord.OrderId}, '{ord.Customer}', {ord.Price});"; var command = new Dictionary(){ @@ -515,6 +500,15 @@ using var client = new DaprClientBuilder().Build(); sqlText} }; Console.WriteLine(sqlText); + } +}); +``` + +The `batch-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "#componentbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. + +```csharp +// Insert order using Dapr output binding via Dapr Client SDK +await client.InvokeBindingAsync(bindingName: sqlBindingName, operation: "exec", data: "", metadata: command); ``` ### Step 4: View the output of the job @@ -905,24 +899,21 @@ dapr run --app-id batch-sdk --app-port 6002 --dapr-http-port 3502 --dapr-grpc-po The code inside the `process_batch` function is executed every 10 seconds (defined in [`binding-cron.yaml`]({{< ref "#componentsbinding-cronyaml-component-file" >}}) in the `components` directory). The binding trigger looks for a route called via HTTP POST in your Flask application by the Dapr sidecar. ```go -func processCron(w http.ResponseWriter, r *http.Request) { - fileContent, err := os.Open("../../orders.json") -} + // Triggered by Dapr input binding + r.HandleFunc("/"+cronBindingName, processBatch).Methods("POST") ``` The `batch-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "#componentbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. ```go -client, err := dapr.NewClient() - // ... -sqlCmd := fmt.Sprintf("insert into orders (orderid, customer, price) values (%d, '%s', %s);", order.OrderId, order.Customer, strconv.FormatFloat(order.Price, 'f', 2, 64)) -fmt.Println(sqlCmd) -in := &dapr.InvokeBindingRequest{ - Name: bindingName, - Operation: "exec", - Data: []byte(""), - Metadata: map[string]string{"sql": sqlCmd}, -} + // Insert order using Dapr output binding via Dapr SDK + in := &dapr.InvokeBindingRequest{ + Name: sqlBindingName, + Operation: "exec", + Data: []byte(""), + Metadata: map[string]string{"sql": sqlCmd}, + } + ``` ### Step 4: View the output of the job From 9ffc030f2f5f19796bb2daec868fb78e8105fb22 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Mon, 27 Jun 2022 17:17:32 -0500 Subject: [PATCH 32/42] quickstart_descriptions Signed-off-by: Hannah Hunter --- .../quickstarts/bindings-quickstart.md | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index 7092dd2e0..50235d302 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -99,7 +99,16 @@ def process_batch(): The `batch-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "#componentbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. ```python -try: +with DaprClient() as d: + sqlCmd = ('insert into orders (orderid, customer, price) values ' + + '(%s, \'%s\', %s)' % (order_line['orderid'], + order_line['customer'], + order_line['price'])) + payload = {'sql': sqlCmd} + + print(sqlCmd, flush=True) + + try: # Insert order using Dapr output binding via HTTP Post resp = d.invoke_binding(binding_name=sql_binding, operation='exec', binding_metadata=payload, data='') @@ -906,6 +915,18 @@ The code inside the `process_batch` function is executed every 10 seconds (defin The `batch-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "#componentbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. ```go +func sqlOutput(order Order) (err error) { + + client, err := dapr.NewClient() + if err != nil { + return err + } + + ctx := context.Background() + + sqlCmd := fmt.Sprintf("insert into orders (orderid, customer, price) values (%d, '%s', %s);", order.OrderId, order.Customer, strconv.FormatFloat(order.Price, 'f', 2, 64)) + fmt.Println(sqlCmd) + // Insert order using Dapr output binding via Dapr SDK in := &dapr.InvokeBindingRequest{ Name: sqlBindingName, @@ -913,7 +934,13 @@ The `batch-sdk` service uses the PostgreSQL output binding defined in the [`bind Data: []byte(""), Metadata: map[string]string{"sql": sqlCmd}, } + err = client.InvokeOutputBinding(ctx, in) + if err != nil { + return err + } + return nil +} ``` ### Step 4: View the output of the job From ac6043c907ef604242fda2a161c6d86776bc49da Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Mon, 27 Jun 2022 17:31:09 -0500 Subject: [PATCH 33/42] csharp Signed-off-by: Hannah Hunter --- .../quickstarts/bindings-quickstart.md | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md index 50235d302..9744488f4 100644 --- a/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md +++ b/daprdocs/content/en/getting-started/quickstarts/bindings-quickstart.md @@ -497,25 +497,26 @@ The code inside the `process_batch` function is executed every 10 seconds (defin ```csharp app.MapPost("/" + cronBindingName, async () => { - - Console.WriteLine("Processing batch.."); - string jsonFile = File.ReadAllText("../../../orders.json"); - var ordersArray = JsonSerializer.Deserialize(jsonFile); - using var client = new DaprClientBuilder().Build(); - foreach(Order ord in ordersArray?.orders ?? new Order[] {}){ - var sqlText = $"insert into orders (orderid, customer, price) values ({ord.OrderId}, '{ord.Customer}', {ord.Price});"; - var command = new Dictionary(){ - {"sql", - sqlText} - }; - Console.WriteLine(sqlText); - } +// ... }); ``` The `batch-sdk` service uses the PostgreSQL output binding defined in the [`binding-postgres.yaml`]({{< ref "#componentbinding-postgresyaml-component-file" >}}) component to insert the `OrderId`, `Customer`, and `Price` records into the `orders` table. ```csharp +// ... +string jsonFile = File.ReadAllText("../../../orders.json"); +var ordersArray = JsonSerializer.Deserialize(jsonFile); +using var client = new DaprClientBuilder().Build(); +foreach(Order ord in ordersArray?.orders ?? new Order[] {}){ + var sqlText = $"insert into orders (orderid, customer, price) values ({ord.OrderId}, '{ord.Customer}', {ord.Price});"; + var command = new Dictionary(){ + {"sql", + sqlText} + }; +// ... +} + // Insert order using Dapr output binding via Dapr Client SDK await client.InvokeBindingAsync(bindingName: sqlBindingName, operation: "exec", data: "", metadata: command); ``` From 3930808a09b0549a44e2788aec74d010500c2888 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Tue, 28 Jun 2022 09:33:36 -0500 Subject: [PATCH 34/42] remove helm section and link to dapr aks extension Signed-off-by: Hannah Hunter --- .../hosting/kubernetes/cluster/setup-aks.md | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/daprdocs/content/en/operations/hosting/kubernetes/cluster/setup-aks.md b/daprdocs/content/en/operations/hosting/kubernetes/cluster/setup-aks.md index 910466cb7..87d27dbc1 100644 --- a/daprdocs/content/en/operations/hosting/kubernetes/cluster/setup-aks.md +++ b/daprdocs/content/en/operations/hosting/kubernetes/cluster/setup-aks.md @@ -51,14 +51,6 @@ az aks create --resource-group [your_resource_group] --name [your_aks_cluster_na az aks get-credentials -n [your_aks_cluster_name] -g [your_resource_group] ``` -## (optional) Install Helm v3 +## Next steps -1. [Install Helm v3 client](https://helm.sh/docs/intro/install/) - -> **Note:** The latest Dapr helm chart no longer supports Helm v2. Please migrate from helm v2 to helm v3 by following [this guide](https://helm.sh/blog/migrate-from-helm-v2-to-helm-v3/). - -2. In case you need permissions the kubernetes dashboard (i.e. configmaps is forbidden: User "system:serviceaccount:kube-system:kubernetes-dashboard" cannot list configmaps in the namespace "default", etc.) execute this command - -```bash -kubectl create clusterrolebinding kubernetes-dashboard -n kube-system --clusterrole=cluster-admin --serviceaccount=kube-system:kubernetes-dashboard -``` \ No newline at end of file +{{< button text="Install Dapr using the AKS Dapr extension >>" page="azure-kubernetes-service-extension" >}} From 8066950aa1da0a2ffdc99b752ca871bd4d42494b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20G=C3=B6tz?= Date: Wed, 29 Jun 2022 18:51:23 +0200 Subject: [PATCH 35/42] Add hint on OPTIONS request for input bindings (#2587) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When creating an input binding dapr makes an `OPTIONS` call on the specified endpoint. If the request fails, the subscription is dropped and input wont be handled. Signed-off-by: Malte Götz --- .../building-blocks/bindings/howto-triggers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-triggers.md b/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-triggers.md index 636994293..23b5b773b 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-triggers.md +++ b/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-triggers.md @@ -96,7 +96,7 @@ spec: ## Listen for incoming events (input binding) -Configure your application to receive incoming events. If using HTTP, you need to listen on a `POST` endpoint with the name of the binding, as specified in `metadata.name` in the `binding.yaml` file. +Configure your application to receive incoming events. If using HTTP, you need to listen on a `POST` endpoint with the name of the binding, as specified in `metadata.name` in the `binding.yaml` file. Additionally make sure that your application allows dapr to make an `OPTIONS` request for this endpoint. Below are code examples that leverage Dapr SDKs to demonstrate an output binding. @@ -270,4 +270,4 @@ Event delivery guarantees are controlled by the binding implementation. Dependin * [Bindings building block]({{< ref bindings >}}) * [Bindings API]({{< ref bindings_api.md >}}) * [Components concept]({{< ref components-concept.md >}}) -* [Supported bindings]({{< ref supported-bindings >}}) \ No newline at end of file +* [Supported bindings]({{< ref supported-bindings >}}) From 490c6afe44d17a601c01541815d5c27eab6580d1 Mon Sep 17 00:00:00 2001 From: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> Date: Thu, 30 Jun 2022 15:04:03 -0500 Subject: [PATCH 36/42] [JetStream] Enabling on NATS server (#2584) * initial addition of jetstream flag Signed-off-by: Hannah Hunter * for review Signed-off-by: Hannah Hunter * updates per Bernd Signed-off-by: Hannah Hunter Co-authored-by: Mark Fussell --- .../supported-pubsub/setup-jetstream.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-jetstream.md b/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-jetstream.md index 3b683326e..bd3a57e0d 100644 --- a/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-jetstream.md +++ b/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-jetstream.md @@ -79,11 +79,17 @@ Install NATS JetStream on Kubernetes by using the [helm](https://github.com/nats ```bash helm repo add nats https://nats-io.github.io/k8s/helm/charts/ -helm install my-nats nats/nats +helm install --set nats.jetstream.enabled=true my-nats nats/nats ``` -This installs a single NATS server into the `default` namespace. To interact -with NATS, find the service with: `kubectl get svc my-nats`. +This installs a single NATS server into the `default` namespace. To interact with NATS, find the service with: + +```bash +kubectl get svc my-nats +``` + +For more information on helm chart settings, see the [Helm chart documentation](https://helm.sh/docs/helm/helm_install/). + {{% /codetab %}} {{< /tabs >}} From 31f641f829f0cfe59babd2915818b9d26ef8a05c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20G=C3=B6tz?= Date: Fri, 1 Jul 2022 23:19:04 +0200 Subject: [PATCH 37/42] Fixed indentation of RabbitMQ binding spec (#2586) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is my commit message Signed-off-by: Malte Goetz Signed-off-by: Malte Götz Co-authored-by: Mark Fussell --- .../components-reference/supported-bindings/rabbitmq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daprdocs/content/en/reference/components-reference/supported-bindings/rabbitmq.md b/daprdocs/content/en/reference/components-reference/supported-bindings/rabbitmq.md index b548d9872..c638bf12f 100644 --- a/daprdocs/content/en/reference/components-reference/supported-bindings/rabbitmq.md +++ b/daprdocs/content/en/reference/components-reference/supported-bindings/rabbitmq.md @@ -38,7 +38,7 @@ spec: value: false - name: maxPriority value: 5 -- name: contentType + - name: contentType value: "text/plain" ``` From 96165997eed614917836595362fe8a3dd1946a76 Mon Sep 17 00:00:00 2001 From: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> Date: Tue, 5 Jul 2022 16:15:48 -0500 Subject: [PATCH 38/42] add suggested note (#2602) Signed-off-by: Hannah Hunter --- daprdocs/content/en/getting-started/install-dapr-cli.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/daprdocs/content/en/getting-started/install-dapr-cli.md b/daprdocs/content/en/getting-started/install-dapr-cli.md index aef7cbca1..4b79602db 100644 --- a/daprdocs/content/en/getting-started/install-dapr-cli.md +++ b/daprdocs/content/en/getting-started/install-dapr-cli.md @@ -49,6 +49,8 @@ Install the latest windows Dapr cli to `C:\dapr` and add this directory to the U powershell -Command "iwr -useb https://raw.githubusercontent.com/dapr/cli/master/install/install.ps1 | iex" ``` +**Note:** Updates to PATH might not be visible until you restart your terminal application. + #### Install without administrative rights If you do not have admin rights, you can install Dapr to an alternate directory via the `DAPR_INSTALL_DIR` environment variable. From dd445be31f12d3e00b75e8055aca721dbff0b406 Mon Sep 17 00:00:00 2001 From: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> Date: Tue, 5 Jul 2022 17:32:10 -0500 Subject: [PATCH 39/42] [Bindings] Docset refresh (#2595) * bindings initial refresh Signed-off-by: Hannah Hunter * updates per Mark Signed-off-by: Hannah Hunter Co-authored-by: Mark Fussell --- .../bindings/bindings-overview.md | 56 +++++++++++------- .../bindings/howto-bindings.md | 34 +++++------ .../bindings/howto-triggers.md | 46 ++++++++------ .../building-block-input-binding-example.png | Bin 88366 -> 0 bytes .../building-block-output-binding-example.png | Bin 95677 -> 0 bytes .../howto-bindings/kafka-output-binding.png | Bin 0 -> 25580 bytes .../howto-triggers/kafka-input-binding.png | Bin 0 -> 24938 bytes 7 files changed, 79 insertions(+), 57 deletions(-) delete mode 100644 daprdocs/static/images/building-block-input-binding-example.png delete mode 100644 daprdocs/static/images/building-block-output-binding-example.png create mode 100644 daprdocs/static/images/howto-bindings/kafka-output-binding.png create mode 100644 daprdocs/static/images/howto-triggers/kafka-input-binding.png diff --git a/daprdocs/content/en/developing-applications/building-blocks/bindings/bindings-overview.md b/daprdocs/content/en/developing-applications/building-blocks/bindings/bindings-overview.md index a2a229425..ccc1007d2 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/bindings/bindings-overview.md +++ b/daprdocs/content/en/developing-applications/building-blocks/bindings/bindings-overview.md @@ -6,51 +6,67 @@ weight: 100 description: Overview of the bindings API building block --- -Using Dapr's bindings API, you can both trigger your app with events coming in from external systems and interface with external systems. In addition, the Dapr binding API enables you to: +Using Dapr's bindings API, you can trigger your app with events coming in from external systems and interface with external systems. With the bindings API, you can: -- Remove the complexities of connecting to and polling from messaging systems, such as queues and message buses -- Focus on business logic, instead of the implementation details of how to interact with a system -- Keep your code free from SDKs or libraries -- Handle retries and failure recovery -- Switch between bindings at run time -- Build portable applications with environment-specific bindings set up and no code changes required +- Avoid the complexities of connecting to and polling from messaging systems, such as queues and message buses. +- Focus on business logic, instead of the implementation details of interacting with a system. +- Keep your code free from SDKs or libraries. +- Handle retries and failure recovery. +- Switch between bindings at runtime. +- Build portable applications with environment-specific bindings set-up and no required code changes. For example, with bindings, your microservice can respond to incoming Twilio/SMS messages without: - Adding or configuring a third-party Twilio SDK -- Worrying about polling from Twilio (or using websockets, etc.) +- Worrying about polling from Twilio (or using WebSockets, etc.) {{% alert title="Note" color="primary" %}} - Bindings are developed independently of Dapr runtime. You can [view and contribute to the bindings](https://github.com/dapr/components-contrib/tree/master/bindings). - +Bindings are developed independently of Dapr runtime. You can [view and contribute to the bindings](https://github.com/dapr/components-contrib/tree/master/bindings). {{% /alert %}} ## Input bindings -With input bindings, you can trigger your application when an event from an external resource has occurred. An optional payload and metadata may be sent with the request. +With input bindings, you can trigger your application when an event from an external resource occurs. An optional payload and metadata may be sent with the request. -In order to receive events from an input binding: +To receive events from an input binding: -1. Define the component YAML that describes the type of binding and its metadata (connection info, etc.). -2. Listen on an HTTP endpoint for the incoming event, or use the gRPC proto library to get incoming events. +1. Define the component YAML that describes the binding type and its metadata (connection info, etc.). +1. Listen for the incoming event using: + - An HTTP endpoint + - The gRPC proto library to get incoming events. {{% alert title="Note" color="primary" %}} - On startup, Dapr sends [an OPTIONS request]({{< ref "bindings_api.md#invoking-service-code-through-input-bindings" >}}) for all defined input bindings to the application and expects a status code 2xx or 405 if this application wants to subscribe to the binding. + On startup, Dapr sends [an OPTIONS request]({{< ref "bindings_api.md#invoking-service-code-through-input-bindings" >}}) for all defined input bindings to the application. If the application wants to subscribe to the binding, Dapr expects a status code of 2xx or 405. {{% /alert %}} -Read the [Create an event-driven app using input bindings]({{< ref howto-triggers.md >}}) page to get started with input bindings. +Read the [Create an event-driven app using input bindings guide]({{< ref howto-triggers.md >}}) to get started with input bindings. ## Output bindings With output bindings, you can invoke external resources. An optional payload and metadata can be sent with the invocation request. -In order to invoke an output binding: +To invoke an output binding: -1. Define the component YAML that describes the type of binding and its metadata (connection info, etc.). +1. Define the component YAML that describes the binding type and its metadata (connection info, etc.). 2. Use the HTTP endpoint or gRPC method to invoke the binding with an optional payload. -Read the [Use output bindings to interface with external resources]({{< ref howto-bindings.md >}}) page to get started with output bindings. +Read the [Use output bindings to interface with external resources guide]({{< ref howto-bindings.md >}}) to get started with output bindings. + +## Try out bindings + +### Quickstarts and tutorials + +Want to put the Dapr bindings API to the test? Walk through the following quickstart and tutorials to see bindings in action: + +| Quickstart/tutorial | Description | +| ------------------- | ----------- | +| [Bindings quickstart]({{< ref bindings-quickstart.md >}}) | Work with external systems using input bindings to respond to events and output bindings to call operations. | +| [Bindings tutorial](https://github.com/dapr/quickstarts/tree/master/tutorials/bindings) | Demonstrates how to use Dapr to create input and output bindings to other components. Uses bindings to Kafka. | + +### Start using bindings directly in your app + +Want to skip the quickstarts? Not a problem. You can try out the bindings building block directly in your application to invoke output bindings and trigger input bindings. After [Dapr is installed]({{< ref "getting-started/_index.md" >}}), you can begin using the bindings API starting with [the input bindings how-to guide]({{< ref howto-triggers.md >}}). ## Next Steps @@ -58,4 +74,4 @@ Read the [Use output bindings to interface with external resources]({{< ref howt - [How-To: Trigger a service from different resources with input bindings]({{< ref howto-triggers.md >}}) - [How-To: Use output bindings to interface with external resources]({{< ref howto-bindings.md >}}) - Try out the [bindings tutorial](https://github.com/dapr/quickstarts/tree/master/tutorials/bindings/README.md) to experiment with binding to a Kafka queue. -- Read the [bindings API specification]({{< ref bindings_api.md >}}) +- Read the [bindings API specification]({{< ref bindings_api.md >}}) \ No newline at end of file diff --git a/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-bindings.md b/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-bindings.md index e0829287c..cec770ff3 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-bindings.md +++ b/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-bindings.md @@ -6,23 +6,31 @@ description: "Invoke external systems with output bindings" weight: 300 --- -With output bindings, you can invoke external resources without depending on special SDK or libraries. An output binding represents a resource that Dapr uses to invoke and send messages to. For a complete sample showing output bindings, [walk through the tutorial](https://github.com/dapr/quickstarts/tree/master/tutorials/bindings). +With output bindings, you can invoke external resources. An optional payload and metadata can be sent with the invocation request. -Diagram showing bindings of example service +Diagram showing bindings of example service -This guide uses a Kafka binding as an example. You can find your preferred binding spec from [the list of bindings components]({{< ref setup-bindings >}}). +This guide uses a Kafka binding as an example. You can find your preferred binding spec from [the list of bindings components]({{< ref setup-bindings >}}). In this guide: + +1. The example invokes the `/binding` endpoint with `checkout`, the name of the binding to invoke. +1. The payload goes inside the mandatory `data` field, and can be any JSON serializable value. +1. The `operation` field tells the binding what action it needs to take. For example, [the Kafka binding supports the `create` operation]({{< ref "kafka.md#binding-support" >}}). + - You can check [which operations (specific to each component) are supported for every output binding]({{< ref supported-bindings >}}). + +{{% alert title="Note" color="primary" %}} + If you haven't already, [try out the bindings quickstart]({{< ref bindings-quickstart.md >}}) for a quick walk-through on how to use the bindings API. + +{{% /alert %}} ## Create a binding -Create a new binding component with the name of `checkout`. +Create a `binding.yaml` file and save to a `components` sub-folder in your application directory. -Within the `metadata` section, configure Kafka-related properties, such as: +Create a new binding component named `checkout`. Within the `metadata` section, configure the following Kafka-related properties: - The topic to which you'll publish the message - The broker -Create the following `binding.yaml` file and save to a `components` sub-folder in your application directory. - {{< tabs "Self-Hosted (CLI)" Kubernetes >}} {{% codetab %}} @@ -89,7 +97,7 @@ spec: ## Send an event (output binding) -Below are code examples that leverage Dapr SDKs to interact with an output binding. +The code examples below leverage Dapr SDKs to invoke the output bindings endpoint on a running Dapr instance. {{< tabs Dotnet Java Python Go JavaScript>}} @@ -277,22 +285,12 @@ function sleep(ms) { {{< /tabs >}} -Invoke the output bindings endpoint on a running Dapr instance. - You can also invoke the output bindings endpoint using HTTP: ```bash curl -X POST -H 'Content-Type: application/json' http://localhost:3601/v1.0/bindings/checkout -d '{ "data": 100, "operation": "create" }' ``` -As seen above: - -1. The example invoked the `/binding` endpoint with `checkout`, the name of the binding to invoke. -1. The payload goes inside the mandatory `data` field, and can be any JSON serializable value. -1. The `operation` field tells the binding what action it needs to take. For example, [the Kafka binding supports the `create` operation]({{< ref "kafka.md#binding-support" >}}). - -You can check [which operations (specific to each component) are supported for every output binding]({{< ref supported-bindings >}}). - Watch this [video](https://www.youtube.com/watch?v=ysklxm81MTs&feature=youtu.be&t=1960) on how to use bi-directional output bindings.
diff --git a/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-triggers.md b/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-triggers.md index 23b5b773b..c8ceb8836 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-triggers.md +++ b/daprdocs/content/en/developing-applications/building-blocks/bindings/howto-triggers.md @@ -6,29 +6,36 @@ description: "Use Dapr input bindings to trigger event driven applications" weight: 200 --- -Using bindings, your code can be triggered with incoming events from different resources which can be anything: a queue, messaging pipeline, cloud-service, filesystem etc. +With input bindings, you can trigger your application when an event from an external resource occurs. An external resource could be a queue, messaging pipeline, cloud-service, filesystem, etc. An optional payload and metadata may be sent with the request. -This is ideal for event-driven processing, data pipelines, or generally reacting to events and performing further processing. +Input bindings are ideal for event-driven processing, data pipelines, or generally reacting to events and performing further processing. Dapr input bindings allow you to: -Dapr bindings allow you to: +- Receive events without including specific SDKs or libraries +- Replace bindings without changing your code +- Focus on business logic and not the event resource implementation -* Receive events without including specific SDKs or libraries -* Replace bindings without changing your code -* Focus on business logic and not the event resource implementation +Diagram showing bindings of example service -An input binding represents a resource that Dapr uses to read events from and push to your application. Read the [bindings overview for more information]({{}}). +This guide uses a Kafka binding as an example. You can find your preferred binding spec from [the list of bindings components]({{< ref setup-bindings >}}). In this guide: -Diagram showing bindings of example service +1. The example invokes the `/binding` endpoint with `checkout`, the name of the binding to invoke. +1. The payload goes inside the mandatory `data` field, and can be any JSON serializable value. +1. The `operation` field tells the binding what action it needs to take. For example, [the Kafka binding supports the `create` operation]({{< ref "kafka.md#binding-support" >}}). + - You can check [which operations (specific to each component) are supported for every output binding]({{< ref supported-bindings >}}). -This guide uses a Kafka binding as an example. You can find your preferred binding spec from [the list of bindings components]({{< ref setup-bindings >}}). +{{% alert title="Note" color="primary" %}} + If you haven't already, [try out the bindings quickstart]({{< ref bindings-quickstart.md >}}) for a quick walk-through on how to use the bindings API. + +{{% /alert %}} ## Create a binding -Create a new binding component with the name of `checkout`. +Create a `binding.yaml` file and save to a `components` sub-folder in your application directory. -Inside the `metadata` section, configure Kafka-related properties, such as the topic to publish the message to and the broker. +Create a new binding component named `checkout`. Within the `metadata` section, configure the following Kafka-related properties: -Create the following `binding.yaml` file and save it to a `components` sub-folder in your application directory. +- The topic to which you'll publish the message +- The broker {{< tabs "Self-Hosted (CLI)" Kubernetes >}} @@ -96,7 +103,9 @@ spec: ## Listen for incoming events (input binding) -Configure your application to receive incoming events. If using HTTP, you need to listen on a `POST` endpoint with the name of the binding, as specified in `metadata.name` in the `binding.yaml` file. Additionally make sure that your application allows dapr to make an `OPTIONS` request for this endpoint. +Configure your application to receive incoming events. If you're using HTTP, you need to: +- Listen on a `POST` endpoint with the name of the binding, as specified in `metadata.name` in the `binding.yaml` file. +- Verify your application allows Dapr to make an `OPTIONS` request for this endpoint. Below are code examples that leverage Dapr SDKs to demonstrate an output binding. @@ -249,8 +258,7 @@ Tell Dapr the event was not processed correctly in your application and schedule ### Specifying a custom route -By default, incoming events will be sent to an HTTP endpoint that corresponds to the name of the input binding. -You can override this by setting the following metadata property in `binding.yaml`: +By default, incoming events will be sent to an HTTP endpoint that corresponds to the name of the input binding. You can override this by setting the following metadata property in `binding.yaml`: ```yaml name: mybinding @@ -267,7 +275,7 @@ Event delivery guarantees are controlled by the binding implementation. Dependin ## References -* [Bindings building block]({{< ref bindings >}}) -* [Bindings API]({{< ref bindings_api.md >}}) -* [Components concept]({{< ref components-concept.md >}}) -* [Supported bindings]({{< ref supported-bindings >}}) +- [Bindings building block]({{< ref bindings >}}) +- [Bindings API]({{< ref bindings_api.md >}}) +- [Components concept]({{< ref components-concept.md >}}) +- [Supported bindings]({{< ref supported-bindings >}}) \ No newline at end of file diff --git a/daprdocs/static/images/building-block-input-binding-example.png b/daprdocs/static/images/building-block-input-binding-example.png deleted file mode 100644 index 408c373786918a32c28bfd2005d5894b630b8162..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 88366 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

tM@)75JskdWj~tbSGCM0^uyW_V(3A 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 PfPbc^El-u7bdUQ#)hN`t diff --git a/daprdocs/static/images/building-block-output-binding-example.png b/daprdocs/static/images/building-block-output-binding-example.png deleted file mode 100644 index ac114b4bd1251e6b8be90b70ad4babd275b28ba1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 95677 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

@HpLe&nH( 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 E0aH9l9smFU diff --git a/daprdocs/static/images/howto-bindings/kafka-output-binding.png b/daprdocs/static/images/howto-bindings/kafka-output-binding.png new file mode 100644 index 0000000000000000000000000000000000000000..a565e944ad5c2e5c41dc71fd62ebccece8e35ddb GIT binary patch literal 25580 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 literal 0 HcmV?d00001 diff --git a/daprdocs/static/images/howto-triggers/kafka-input-binding.png b/daprdocs/static/images/howto-triggers/kafka-input-binding.png new file mode 100644 index 0000000000000000000000000000000000000000..84873e0aa01f61bbe64ac9593797f1a07f4e55a5 GIT binary patch literal 24938 zcmd4(g;!Nyv_1|WQc@J@?k+(}Qt9q)1W{VLQ$awwq(hKSrBi7srMp8oE)qJA-zoGN0!G)CXWcJgL0$j*g`_`xmffi2^b!81c4v4 z=~QX;N2sW%Xxfh$;+K5Y)RvfCAFlHZBrzmfZEanch|ju?EG#sU%EE59mt14jWMyTa zf>}WNW2){0|NSSV6Yg^YsuY{9@meC*NjAU>+2IuRfL|8NmD(BJ=C1p)~QNl40U zzj!ki!8cG>hN{C#{dfIKACeatV*V`Z#9T#G5{WK*ZZ0o1o5?WQpQt~5maEw~Fq*mm z@uK*54-Iiufr4t>cW3^mDtHDZ>Lc1uIdU~WD_kIXp(AeS_rxb0vLQ^UWZM0PbuMon zH$$`f;sS|4;NL~Lt>QSpJ-6ENV)NB)s21x2!Q*?qbJPGFZ7H zC1`zxQu{(gqJWfdue|#7$kK2UxW3hR~ z%ch{nyfk9g9q}MPDRVG8;ny)(3Vovm1b*7px~xM4j~&^}1SBtzHc@exeLkzd>1X{I?qEmzLL0Pi%*Y#n#J1 z#1KzCKt}nrzB^e4;};UrcSnMFr<%7z6z(%GT7kfmaE_yRM#EqKLGR?e#KV-O(XjaW z9#dziATI$0Lc@)pICep)u+YA}dw_yznncuH$o|&%A(Q>Gt2Ml)dxJon1PvC+hjZkZ zfV;#m;(3rs#imj%010AGNI0X6!yzIp zM?5bAo`3Q{<3-31Ej2O5=;GpHdum1jh-5tj+h=Y`MFD5+>Z21*T~^UJ8S)?sTAof3 zp%|D)m@EytdV<%)Z`654O1_BZIh$V2Ek8AOD?Ztu}RXdj@%B`w$%erC-; zI^)2Ci};zd#7EKOy?^H82E8_ok1ZhCLe@qkb?B&J3Nra6h_zxIEWl1HKfcX?_o=88Q{II3X7oMu%th{Brtr= z$0zS%{s)}|2L)wxBI$;d4vf{OTc!LkNeLY%%xG$8*`2$?SUX(dUCQc zFlGUQJPdXD>90)%!@rNQ$~m|qs9x9 z&~9$4u2=tE$ozsa!fN^yQYrLK*DR>JYK`uL4Ec&X29ERlpMu<8XOJ0JSY|tfRV-`y zr%ZfDj#^JOgvcSNfrf|1m!Rd~Cp%_mI`BUR9|}(0#6sxUc{->4$QiZL61vg7o*|>y zYpiTNFx7z+jo4)C#7Rh_>0>{HMPu*-B@!hKMuO)S4?DH~l>FniYy9i!$(`o-*kxAK zo`PX9fnzC&ttFTv4KfO^Mn4gQsYCAHxMJr8zYgtuWaB&{hhh? zv{RixqrivkUKa8yt~hr}hlZ__)6Xwb2gmvkI)ON{)Ss6Yy91Z=NUhUp*jw0fBLxKo zF4zo>23z^Kc}U4W!R~wr>r~fP|Kx*x{}pmbrvZi^$|(HGqla|G3S`kbMII%P`{)tL zr�(^5X_{ul8@me4}iS2-V|4LjBl3peZ7>lYjv^G+x8aN8}zIX|y2!=P@7a0IPA( z`7X4`YopxwL&Q`LWmWSj4nzcsfGOzm4N30`1U`>89<~+!e{rO=X z?{dxMwS@whHZOOq@{vVz)M_jVyOiBuJz`vCCWlr=Sl?&QQna%WC41+Iq_s`GCcz8$TS$K9azZ6-w35KdPLHS zhelVsW`flCVdMSsdezsWlZ?l*D^Tco{tJ11QdNGMD)6rN`Hy0bA0ok64$NQPu1YT= zwVHLM_t;6J?mUb$LPbB6q{Wy%c0_WC?u3Lk<-I=M1?EE<{9|0>me$j28`30c9`s{D zpS{trM{*I#C8~3!iRCiRvo-3UA2xR^r8KTX4o32pF+Y+f@OI{2(g=#ez(E-3LP+O| z0n1)opqD3->SGdfp6FdvJytbyNz=z9qG&x7Sm=k(I+2i3aKbtvzyb)wv4jXjm)s@m z!Q-EM-9y-)ki^-bhW(WO6ZW%5}t)T=1UDAJJphog| z5iixS)FR&b`b>%q|KB_P1TB7|VsU%X7uBq8rkYLpcd{UExLn5bus5nvNW^N!+rSE@ zUB0@!{5!=jjpp_EK}~R=n7Jq_I>}JD)^w(X`%ZQXbZPucKwI(O6Q9RiqJZx$)jioyKmCRll4k5nWh06ugaCVj*qoYF( z6HND-)jaAQ#qM|Q>~aEL_auzMmF49pzXb6ikOkz`FZt0e?ISe_N-{B@Nxm*U4kMzX za7g$+4BMNOZDOw84i7jSALXDH_v^uv*qfFLqWt${sEg1v2mO~Bc>65h^{e7MzZ>c>CKf%D~Elya8UmD#ZfjSpSvJ^|3ru0 zLxJ9i@;`IW?gI8h|KEEpDbX8&vLeIQaiW zD2Y#G+@^#W^wGb`1o0Y+w9zy&V8%Qq0g}S$?;#xpBK)7lY`B=RY$0aqXDngzVd1!@ znd|qw+5Y?Y?^QAc92T3;7Mfglc6JIClWl+JzUYgg986{}Y6$v6x^stPMd-;xd+(fo z05RnfW_7q+8FlN+6V5qpJe%5WMzMO4|6WN`OH0sx#(CNQ;_Pr4-n5`|O;auG$Cm^G-? z-zb_zg}jo*%WIqg8)8&&4(o(${E{m*CP z>E%kJgJ054*0cFdSD96Xz{5 zHhGGSk}0pMnvzKqzw-Cb7ax`=cD+i!(?4?Sz0u?TkS&}iq@+8it-(+-0sEO+Yo)h1 z6hi9J8xQJSz3IH4^CNdEHF>G&{P=G#nN_nzuSP@;ja$7m-2MIhex-6R7bqltRmsq; zFr2)YvxTK{n`MjpUr(C_Ry0FoW2xFKd$1PYh5!Ejo71S?%F60=e_ju76J@qZ^n+;p ze?o9^4hwewx5qK^IF}oVY616GHj~L-znk5mXxK#d&u(CY+&5>?ZP)!JEPOUgOG_Xr zZDI(7AV1SMq2Qk;b;c(p5%9l#@ph(qRphXByih4MH#fJlvoph~{i>p2De}`^DV2(% zVnS!N>$d778dg^NA9k}svA1Id&)s+B8-N4jZaYml`?PchowgYX;28~^Y4JS#ohPNE zSKrW-+rOlY$zPn^Kc=()=ZjofC3_yVPP#r#OlVJ{i-v2D zX*R;|E|$l{Jr5Shom!89{7S>i6&4(3Yd1fU@@ebUryeF8>MSDD#CKf_ZOU79C$|uq zG&;YiPukyXDPZ^Yx;^f5;0^V89B{QsJZaMEb?nfvxbD{13KcDJno)=89eyI)U>uZA_VM$`ERZyV{^Hj3%tE1`H3xwk^4 zv<#xf4pt2?y8hQN={mdVdTn@RTtBTyYTy$F%;K)ZUSc!9JgVdknzt`x&}NmX@L}sM zo^%f)YuDv22B{Z=vB!kFAcBZ>P*djsWyK<7D|R$AOlK6;2iT87$eBi1*x&+bl%8=< zaM^FX!btF~(j?GxH~#jw<4lv)EHaNz*ZEZM z1V9|sMxt4dH$aw>l|?V&UwvDkSby)?#d2VW_Du7ucIJd;^0DPD_9Ti#&I%`6?Ju&p zlZ|dW34X~lxgKz%8!)9LczdpB+3xkCgS zUb>_-?1_y`_%o>c2bg&$!P>ZFJwheG9xj znV{ps$H(-&F_i4fjP%z}X(T2~wB#Bxn~rBGopZGoSss>949;&jAY(PUTbVe{){dao@c0sEsnnj|naV z)orKcBq-n}Que)%a7>9^!Yx;bifOin@b81QOFW~{VtSO3USx54jk+~Mg!egh4jJ7Y5S5*~Y>{aWPJ)Fgb*%b%}4 zA|*|8w?$QF;lL&^v|nm9Xn-x>-_;XG-yVf#V86KH)@y*NOtFp_nCUcrDEKft{>{v+ z!!h*r<7B(t7~0c-m7N=ED%xm##zFZn^BpJeYFz2#%^I6GKjl!P(Ne75Au%JPp!lBt zefn;#+hz0DP9BF<#*fek9k5^Q&4I%ou!(zPsU_TZwSD!d3%`D?G;V?|!|xm3KN3SF z$o4+j+DVzsmx-F-SjrajEseLGEG_9>?F!eC5^4|EoJzw#?;oFC$k!%ZHgNS)<+q3h@20jPUFU-gO^uf0rhvP%X#q6F2z*9BO}+6qk@oSqo~kfnR!uLykz6$ZN&x)( zWZk9aSt%jOuM|$Zv>v-OI{UOXdNW3ivLE&X;wG7VoU07Hyqb&C@*X#Tzr>avgS{+~ zt^5!cR(iv92b_X`RmC)u+Pis&hBRu=SRlr-uvQ_q+x{m5;|2#ssDg&afz!j+4u6_Y zl43hL>XfQ93#)FdigdFwd?b!ehk82P4u$3M@>m82C;%&pV5}IK5_e)m4iJGj#jjnu zVsQ%!o&WxJ9Kei#^I03sS^X);Z$j?7Nmic#k|?f}jsp7nX13Pa%>Qh1tWe3!XQzFdvRcAY?nR78Hwb`cSA~V_ly<_=Mb9}HDmXkbJVMzPp;lMSKT9ZJ)t=AwjK}u2F?RZ_8 zX^Gh3Mo*g1Q@*RgDEcZ>ef`e}TtW8Uw+CKl(lA6t`h0|mO+PU_+t0D~AeUvp`KrBi z$Rg+!V0NT`Vbc;y&I>r$O^&o`MWTiQu5#IZ+C-;RTO+oVGdU?KX*u9#*ac5_fc#?7 zbGg;~g_cga;y7qgqfIRITe@+)|T7-TMS8l ztbsjB#nNAN)KPSPJNVJ3KkQT4=-CJRx2{-RWn}!e<)&?OE=UO!VH88qs*cKLZ-z8x zE-uv=xgK=k0AU!wKgDv3))U1V0^BPA4^7D71;DCB9~hgK*O}!CqkY3 z`_3?*_ESO?=O9(*X?!+e5+Z*0MJIQ6cl7l15_hLsgAvGf5fKr!8>VAx zTY7s5V4kX)8Xg7)1|A+BCZ>X_syNUHu!`*WEW!*KW%W3{=7%=cch_f>&)wp}v>P0+ zgs7(wh@#3&;;mQDAo>3QZm()R+0*)V;jywr;^l?&hl>Nr!0Q^GEE4;AI7H32sYHK& zv)H71_toUkyV|mF&uPxiAE);C(vxrcHsy{ZozEcJ^HBKjz%~=LMDz0X*GhNtXTDBT zY>NYyPPZ`@DECdYW4U?jK-s@PvuYTXI978D^p)LJeakH5s!{ULKeUoYh1} zp7(r=r=Zj1z>->06!DKP%DKSv;ncH=QA(q4TdTX1A5W{Jq$4upeg0_jD*oZno)1e( zP*6}P<+OGSMaQ)t3yJHuz$DiUF>Ceu1LK@kR8qPD&Y@JhL=*V;bbdQ=SU)|QL3Os! zyS1}vvknl8puit=1l)n3R$<(v*}J~JK1mw^k^m#35(o{$tB#Wqk+C=qhcw^l)|%NbPbM^(;!sb3&=frUrTs%mU%;Gr$TX4JRIwKHRdf`{kK7`+^j;+xnZl9_{W!x zm4pK1+f&@7kDWmjap?hFVYtWdj>l5)1A$I2`<)DzXcbL-5%9ac)t0JH%3tjaMk%$U zT?gh~%1PU8#cQ2~VIjr%9spEKJXTg#+iD1fh=={<(JII|5~-zQUi3dL4%IN5q{Teh zl6Epj9v%cHR&|e>bKaI03Jb>=g&+q8>SXAX9lNet((!<9jD+$1hDQ5`mFZmu)@|bt_Mw44h|GER-T;l$6 z9c)~JqR+*_qODTT=xCLn{^!lxE)aO^D^pVDo^x>>fRw6~U4xd6F5l~TtrV)kkY+#k zec)O(-sO8VxnL!LUd-$PjmC87j<e3sVRQ|!Xs99jF%qWw;nl$w)ezGaAj zNZ4EVwAo!um)XG~x7!ZSO zFz#2tU<#+0&nbzp%LX81Mzh-v$}f7Nh(T5<0pJIKwHyYu(y^~qEyW3+d>eAXUjc5N zI^c43+6?Ym={;ZXpeYHqRM}mHNefuG&ipt71A{)dr%r_-zc(cjm+>0|2ze0f#{+7& z{W+cCGNQ3Y068RX_P&AqpzLv@#^HnP5ua}pjf?Y4G5&5x{+z}UxK**F=B!DDpHuL! zfH8aCTy&C?H^gU+8p7=Q=FhMg)T?Y}ufNk_dI;20cc?YDcg-*(TEdI7N6pni16v!J4AR1)+pz&QY5 zPC{~z`*sC9YubpP*Xy_2eF2}{$&P==I~jR!k&9gVnM^LY@Mv0+yelZNt=&OED<|XPlNU<_-W1& zEY(y{Q%fxxmzwUs1em-a_iDGSDg`JJ2vs?O_Xd;^*IadJ>JDc*9)$;e+{#Q^!|7=@ z#lx;0uIGnkdnzjKzwhiegf@BFueLI{hjh#JYn+xPIy!mr29-fYasl{GD({W>yPN%y zx-(Nvq^p=+W;laYY)=75YwEq3Oe+;8dN!dY75>nFE6v8?; zpP|=r&F_siye22NOc@EVmZr`aqA`K`BDw#)2Q&hF}Yeof-+HG|)r(O+TyT0M}sVkhhJD+zd zT${cd3RLkk`u>Ji20`8!)>;DOR@tMA)A{ zf2jSAf&+#kts)R9dQaW!%{Y+AO?|W3s-j?RIcz;q-T9@VpqI6936S*0WC{wqY3t?6 zkI-dcwQ+HeyiWoAiz4Do7x!FxoO~C+k1OrB0|u!s zjsL32DqQpL;1|Kgg20*&;o*ax29*^F-E=qc%sO&9fM$%9xSxUjo&9FRi0OAWsb?_y z9^>lqMvv2c{r=Hv*JQ(>QnSz5F0d;oCsssidrt7X^V%YFejf8Mh6?6$YtzT^*VhQ{xhYg8r$Mf+m zg5Y&`l7pyn>nm@{suS~JPVSKK8|dizVOzZS1Lvap`)mE#T3J(R4DW7IbgM(y<{-On z`ESZ^VYuWYX?%d&Jc$2Jqw|F)O&K3^2`K0TDlbVVD_wxqN5yZ-Jr9=%*>#hK9UE7} zBAzhc1A4Buu=$%hA_oBApHjr*b{T$`GjX@u;-d1<9VT)pZx~mfRBemf2q==0?;v-o zHvbV~ljA>SYWPSlmMZJnyD`Adx-a|D$+Rny#joqp3*6q_QI1-GJY%BTqH7}Ym&RnV zM%QyCc|$MQ05dU{@n;9aM=mpF0at~kPTD41W)-8Vkp9P*I3PNa3-O$2IbS`}LUuZ78P8%FEzji>s1`B)cL_8``I0WwgAk8Z<%&U z!j*`Nf=6~{<}I*8wJctlX!)?6nvqbe_eMuvDU)Rs_ZKdwY_se{tqkDi~gvT%4NXq zl}SoAe`2FUG|pWiJYy*LM6IG9Vt)Cb&MN0afhY2?2ri|6R{Xl37thFaA50F9Lg)yvc&U}$$@LENAZ={`9@7?ucD~$l@~-5M&&2{3fG4h2s?q!u@(jQCXCyE&L@GxXV_ZAvHWxjRU6^!}Fhc(30G z%NeIVhPsi{?{5H-wAtEh36K7;uVmviqP!)?4;FFjy1MU5Vn37d+WGeH{R{tl1BKVW zf4^&^{taho8u8h#G@FG_1wJrZ`vIUW3D1T#v?nm0-OQ|Gm;A>NhC4%QscW<3c9vE&oNP8pK969id|qE3K2-Q?eE`b ziX1d{xojpxulL0&QPe84Ty%DtdppReV%L>tI?`ahW@ZV|c1vwIEr|-2#lo3N{$8D( zYA>cSW14oLe}LQ-%ifVLbgnU}J1TO~g&DQoRwfIwh03$%m_#usT{nq2-%QtMmsD$i z-2ge<&vSR=+!C_t($f698#UKSL+?u+B zDxjUOMR6M*gc49t+@6lBm5DrTig!1E1p8@dI?AMy&SBj6n|EBYM)>d#;D>O@1@yNB zW@Z|kmVssz(4~4*qJ-7~%axH+gH9hd@2t3V;xk)0$;D8_JC%PM(0@b>~b-Oa#0Tn|t+u6&4;| z!_YJ5cop-bi;D))R{&0c?3SG0wxAifF+D_7{Z~oapvJ^0&6))48gOugv!-*7m^ihY z2o~{dzB*zC+lb>Oq7*}I^Y$0+_2708vYc=rZ04EPQrhK z*ylSt>z$VG0sIcQbKl~a2VB*!4*L}NulEh8=sM-o4!_GmO3mL`QmFE-RWP8h!ECgK z>%)g(MnM7M4UE~9krwKq=d1elw=NcLMIyfQ8;Qmb(4o9{_u+E-s@!g^ZQIyYcdp-X z?P5?utHnuZ(=1lj;dLeV+@?Y;4uk3JsoaLWC--z-jr&Fq15TF=7vHfsjwasU54{Td zU$X;d4{CB--4RdRmyN4Ovc=|^(EHWC`(7M?3a6o&o>tz=4*+@UJJPZts*M1xDmdJM z+G>ulD-#1lfnJp~3cRI;nRtL& zz6PuVkS~B?a?xakjyTECP8tb4K)eKAzJQMz{m`{pkFn;p?SDgbvEMFgNwbnudkIvD*w0=kd&7Nddm*ZqGu$NmJ8$JB*dGN zOm)?=%d|1M@7mm_M8NG@o*QPYB=rIA$zk5*=+!i`l;1*PKmaQGOiu>NEW1X&^!CW~ zqMk3v6W~{)fgl@YtE(f6k2Kyjxr(-PCAh)UPmi{pp{<> zFF>1>Y<~xmJ0QOnwH$Gf(dS)PQVhtC78{oUkk0KZJP!slWUdjIF*?5qy7 z6#|?A6mTqyW8-sS(sb4Wn?Y^C?FycFF)^tafM>3wVmAKcvL*G5E)%6XO75F+_C#a# zOcE0yJ92*@xm0fO?JEL^aeppAi#SHWGjYGhcvV4#3J$cIw(mz{fFvx-|eamjmm!*yRpTRs)&OMVsax;B(r1 zFF@{OZ3Lqd^>V(wJO(^Q;-}-8SFxN%DNT+YXAj24RF#wxrJwqozJZ>Qa3wgUiv9-i z4b%}eqKmcYrtIYUV{@nU)i>g{X4As6l9Ijy_}p$ay_YM27+lJ zSv+&H-jK^qlAjYmAwK70dO9ZUepd)UF_YUY0MuOAVeZ)?Qrv@tCld+SAYdjGSG(*;=BByt@rHaDksi^G?I`EMJ3^rtY8Eqc_echd31l=w%4`Pt*g6jzC$>R z+he(mz^a_$G;{BJxa>k$4j)hxikGqWZ}%wXUP$REh~cZKUl z+!Pff-xp4s`l^Vr0XCqnbW+=h7eTCps8Y~8#Q+zO@ZO|pc^z2sczQlRKGk7UGrKo z&}dBH9Zw3-gnB4IL)6`Jo+sexzia+c{BQ>fBlou_qdpVu!1Z4&`BvGCW&@Vv>OJNY z02E(cS(%im=lKC0D-2n#v%3gE!+uC5THNdJ@9)%hHl-$hRRGdHTLz;kSCWb6I8UEG zb%`@-aHJG+UIF;b+PGrz92DtFbSAk>nxA>Ytd!cg)BrK_1thgVs^`0hGP|(D4tT&q z<2&Drd)MUy<53I1!siG&nOa#DG;90pPL$ZTg1D=pp|RVqBTvF(F6rmj>Z6_CLmw;3 z>vwqsirf8PcwH`!EHE_$wxvKn5CJ5#qAQ5baZv3>JncB~V1}6FZ-?*n6VUq-&Ijlr zMX8eN41PPN!dC6?DU&hZ5@3i#9S$(T&FK#PK48o$P1}6_{)XP4fsTp+Ju}WMe!FuN zJW-*5+sm05{lVvWY$@e{;&wM-Mk}LO#T8sU8alF>cpDAcHfFzBFFq6A0=Z6u?WCgn zW<!mwxfpffXX=Fdp}yC{{bl_;70~f5Ka^U zo*Aorw8=nD>vi}{m0PYTOeUoK+qaZl~Z9w<;_b|}3$)i3@4M5%rn9X4Vqf!{) zcP=6$3E>9ghKg|8*R?iRwyxB&C3~AClP9{R#LTsT8Y`L)F) zsM+zFaZpo}0>XR`&`}cw4#Fhv+DP~Jlcjoa;6}EGGnnNxK|{=y>Dfd=?L;;b#97fF zd6NKi+OaZ;ZHuttx({x`-Na`9Us11cFU9r}kkG^DvRj%}WlEp58(x0ELJ*FivbxLm z;2}kvSTXwzBc|x}-!F&lHdq(MBR&N)yFe&wk^OTrm)8_yat@{CD8Fwc0@t|K%db80mIoluw|45 zXtaf;aSj9-yR%ywG7=v98nkKz`1qQ&R;*`5Uh40zyeFh!Uv`}M4vhng(%jBa?(b{U z?8|#~q$JE=yW)4gZh-Agkz0wE38VK9>gP)oL z?9Rx@$iQ{|0Wlb0l0Vll|GX&vw|QtRSd@(zIw&TwE@?jI;9*AT28N1Vj6H zdv8dq!<7=u8SL8U+pLzjn_roEc^z%#Jb*roqZ|Q^4S*9?OMkWllCk-kSK;o4k2J6Q zdU_P%Kp5!+hH_e*W)%S(oG559Nx|3J9RwaQikRE52u(slVs>aN-~|Li6U&>qpdkHf zj4zXprxTO)0O+_NsM>?-8%xy2#>VH*pF!#~-yH!AOB^ub_yV;{bPAXcA5wuBh;W;A zdt|_Ar=D6?nj~~HRw240<#>5{L3DjWNNBBq+`h#>UGR$Tu}Nbz=)nyW1|7_0 zRafnxeh2#JKqW_dl0QxPe>!q(rz<%n1`#!l1!4e#6XZZ`=MXf1f~`(r*Hd+|ZkoU7UG!Dr~1sct6J0M;g=)UUb(Q+W)HDaJ;DJ`Q0XS@zl4(1pYZl8x~ft-V} z5Dqe1PC=PuHnX*0TcgXXt7LAorRCKSI|wBA5l=XhBRIfhA}%ftm@|;yYA%9~iO>gl zrS&o{E@LBEf%?l#gb;{Vh}-n*bP#z7f{|h_Z*G)ctM3CX04|r?tlii>85BeSizmp* zsRHao~9{-wvnkU%bs)4css;5>UX_U1R$3fFigO-P=VS< zPQY9)6(^N(D;(txbbpmLBc}H>9O(c|kDiv67Ek=r9Fao{g5ok4mt%h%E$D};0>K32 zQGu7M56DLr9_4vpP#;J_Si4I0k2fAaVB5*09vqaZ*M_0?c)CCP|$Wl9#rn$T7aEZ6Fq)^ zfC35nxwTth!-b1zZWprQO#>04-fAGhM($Iw!Iv;9es+`Q)4=% zv1A?uBlXIf2gUn6g{M-d98OW*qzlGg!lITCa8M~>g{_2u(2U(y+6hceGz@g2yP;Hv zcS1lbyCl~VV+82mj{NT%=}z-1NrTP@piJN@%C9(hQ&14)KWi4nl`*uysNtW~x!_~&#`6&-jasV2^pjfK2327R625oV>kAuMxCT+{j zL9}NT#B_lLdEqc7srzkYE`^YPD-8-!|5^~(mHtBon(-xs^@fatZfN4WW4}sWsFczT zG;d+8z7$c32a~%`DE^%*dkhYA*n)Ftvk_QC0RiGV?5F}I#B@9PZV{s0VQzQun0I0S zGYeRh_ANeP`V@AF0c-zT?P?;D751H%?KP%#Ym6axr*BjXT0H)>;r}O=JH^x^J9V*> z@(}3{Yr#$Bjo|Q+ogQYw42_v<^Ao+p1nH+3HeRt{d5wwEAFlBUcaw_^gfBFH7!H_s z_)PMuX=%q|JVR^rc^L$D_1~0(e3P&=lKmqL@d-l~jIEQOE}JS?N+rXB11gQ>HZ)Dm z!Cw74mHIZf&H%eO=uK5qW$7O$-1bSa8C@04%0A5 zdua^bYy=%V{9C7>wju4_j0JLh@X$U*?5c|tS5mstxWP+2{Ek7 zcQ=KTyg+XM6(zcmj5!#zKil+8Q$WN}@uRgJAfVZV`>ve!tF{so5a8eN3O{%GUxk7g z;S<{GJhTPVENo?C(}(`fo10H;R`#v3YjAWwRVOk|K>g3E;4D<1Nr8T_YjiXd%c0o; zRx4%b=s?7CVX7pIs`jPnf0GPS1_SE;%ADfR$aBM_mqx>ukXX(ZBX7MhoyJ^uvYRZe zrQ%=5`OoTt^11pcz?g%M{3s}_24kn4D1s`!RnX5*_sJKvO>ud_MqV{~4RUUz$4(AE z@Tyzg_mb$ES$oLTO|3dXNr3x;X*n_v>9GYk1&W*Tq_)m!`O2w%_9Srd-0jfxVs^FS zj3tf|aM52nL*kDD!fGCqL?%flI!V8g?BUUxr2|KA_ZPf(7n-`y_se$0|9@`H>PYfg zv;S2yK7gsPv~n>4vFg0sq=5GPka`GcbHB4~*GJ7T6N=J9-UCe3O9 z&j({kIsavkdSbx`m%<1v$r0z&0%SzB7xM{|{AA%xP->iDMXUQJZuyPm_*NQG%G`i+MnY3TW)s zfuq)V8!HIs0;pS9jEn|2i21A6O!X_l2{)DfnA8yiJ|SCJ8r@5jpTCa0DORXZ!$PF& zgSP3}AeA7fntYR3oNaZFPH`wjL)S?5!IF@muB&`0q=Dqjjx6gU6}ap5;ZlM z(NIZc4jY$ZVQFs%N2|TTRVNIb4-qp#KV`HbE`3ZqEYazD@iV{k-T5T~Eu~%@opFAh z(qS=+DTZutBTKE)3*@dmCJbur7vN!0G1Ps#)Ew50ZdPIw@APvJb)w9)RU2a#2XWk9 z?S;MM4;nUz_cjd=%dnxY-4fFYT_Feiai>_iAd5!u6Ku&Bv^-u!mMAbhusGtP;1_SF zN}IhMrT7=aZ@gs8gcg8?Q^moWc;-^oR9gfd=*nJk653At&sZu@!kXEeVAFhwd)2u> zLLF2iul-r*on?-=KPcl=EJI%A|5O4;hI)w2764z>iUet3*I}!Ed4*5R#gHZHErYlD z!dCG*@6N{4UczN-!dlB*Qr`>n4zd@8!I#W(urnx1E$Z_2t#a$ZOngdqJQPcW<#%BB zI;UGvHK*DAMI@nb$4!8f--3aJL{78&;LZbcplFA(_AKciu_RX$I)B$%OIMlV4yNGF z)j>}u%UG|2MdcM#MH&zHVjSc~v)d_1NFI?<-J<)WBU4m#dKv)&O2kG2d@f+8dpsgy7yjWvj!3H4^>=bER22nPvFeMV zk>!|7F@MHlFUckzOQ~}(?iXaKy@tTU*+fzj(B2+~x&t>NN=--)P?~46ePkNlX%6i2 z6)^Yg66Lg9T|vF(&6H9LiytdE_C0hczBziW>?1(-Rhm5Z*7|7$>5((PT?(nd-qzpZew*-y z%I&XZ4cwV(`fZjM<;Cu1BXDc81y(UEuY%K4oWlsdT%cpw z_j*TH<4^pk=(ypW&oifyoVI4$tAn&Z(00Q{clh#k0$%61l@&1wI0GvC!kmZKGW3Fu z4YE{by7+r_^m}AXq~C4{Xp2dn{Nn9;Ff^H56F3rS+TiwQD)gqZjABSOflVlxT1?r#;00;0m-3tJ8dUAHDS4^!`i`D_>AL{1{#!QXknOW0>rXctFC z4+Uq93A@op<+LH6iY&USx3lfoYgQxrjI^sv4P&>4cM?-|Z`UkUx#;x!EY>Y z{&a1hv8c=Qj=6V{r81DB2j{WS2_U?wy4$nnl3VOA^D=TW;^+D&iph$*e_Dm#?X5MK z+4P2et_qOwxD25}!=i8{`4ru$?)I1*D>bxO9k5y8#oE#2dL$>7Ef-%7ecYVCMG`9g z1rG;ogrJ520b8ctzgzn&BZfslv&BO~9-LQ9FF+t#q_GN!Mxcl@=>io;V@mss0ytz7 z-(R9#ln;9B9bH+Q-80p!&cpBC!NA{wK#O!I`83Q--=ZbYl3oz!k7&~W7n~fp!;@cn zyeHMMH!arFpV>hD!Hz>07vp z+AOKu*z;;RZ6*zs)9osoy@KzdBm5BxZ(YUbkEfSsmuq%6cHZL}#r%yiFf^2XX<2&k zSs^PcAz^V7&c%~F4&#-NJo887vDT79H-soqn(gm6em(eb@^A z215Nu+^gVXNN3G(Mr`-zS6yj*m_96{rIReoX?ZdkyLqbzP3Hry8~M&%+S*`w^u<#KJ=A?u23Waip3ukk%s@Av!j zCwzax%Xyu1Ug!Bd&;5Lum{w#>jrt=?BxHo$p7f!Omy;!jywH|MsBj3Zg@QNBhCzUf zpnjieUp9?*O7ge*Az|n!N9}XI>Z4zvQ(GMoR%dz&n1=>h<@)?u5&Ak|an9jd{H^Dj zDU`_KLHEph&XmLZ4;VrUB~uKV=kobLPftTXi$<9smIgEDTMrK$`JQqsfyw-^Uu*a5 z2)UV?IW>6L;jJTU4iiCSJ&x48j6+E(P>{WH2Ew91qvG~GzGBC5Cerdmcx~AfIR>YkdOCGCDk}DfVo&MbHLZf z##Y4Qb~ zJao*04$zU-?;cY43*THEuCrM011C1uJ(bk8`%0%Dvnd1ireY_{{{qn* zBJkpi=BilmD5Sjzuv>DW+p^&l9=;s(A!L8Mc7aH&n%mx4PH3V3{{7trropD0-0Ab0 zbuUJB1^|g#b5iM@1uu3{age%3}_48G9n zXD6Wii(feq#7+^H18}lXvI!fEd)~oVe?E{s@NuIdBevPY-H~1mnV;ei+k-DK#M6kr zKRgq_sRz=741UMf4j56Z7I4ME;5hoLEHGW*-E2NdT-sS`t)>y{e5a4z{py{SHEiTS z{;WtC=~rh;3)*;+!k+_i{u(_$n5XUrP3J_m=9huD4vLmmG*gz-(*nE|ST`8?inI%vq9M4*kL?T}KOTjTFAc~q_msXE0CpzY`YFEUWOkil zL8H^;^B*g|iF;Gsec1+iDp}O_dpR*P<2e2bUpd=b-(~EXgCwYrUzo?;)}m&yGXHx7nJ z%ypL|>ynYVt=rTrIE98_se9(%9X9v^6QU0R#&-por@n*yj(ANoa9#JHE=*^Lz5&kJh$~kt66K}czn6U%WHZ&a&To1 zOk{Ij!YqrFH4|gtd7HzAd3Vf7M*zQYnVGjt+TFolir4iD8KZ`2vTt|dh19g=xcw~_ zG%P#i(Z=GC8qrEIFM$Q?Lli*%dE$r46g-+z6aJbfiP#Hab(!6k(NI3^6i5Hoj`sy- z>VXs_tGa62WZ~}ZGrWCPoo!zpcZUaih*|ca`hc-a%O^9whPu;C5a5YX z#eHo)ok~vD2r(W#8bdHCC_Yk;>z^4kz`KfsUk<9Z_!bCr{c`k&IN0cUcYJ@BShUOL z_%X9^vSmjhW+(`CujXi~C?C2J0&SDv`0|IEOh9j!?)+>QFc?uZi;wp|*f5naSZ57~-? z5CgpuG)TW{vZdB2jOu~+vt>{HR$ks**N^m60oCNg>N%~^)jGq*+0y{f>iDaknvuTh z^^F{bvror~jvsNW-w5b3$GJr1Gg-X9WeUb6g*}(5!$cQHm&8pwD9d3xs9fFr%qq4dGqc9&KfPw&-psa3|=v-z&|k_R%vLF4?cF*v<-IbBm!nh?TU!*G^5N`XaBd?@9Gk zrBrhl&s~kgRIj>05MqYKrqupL&IZ~ZH+Yxv9*C#g%NNMb|L*+s7U;AWLe2)|%mebT z=$W5uy~GaGrlhhKYos<5$gttccV!#2=OiW@X)xn9NAyXlh@*lN>uyVXr(}9qqODTW9?i#`pacZ>!dxLCB&1mSYaz;!^F=lo0hS#9+l_-QT~GD&isM zO|aEdg}MIpT?U;}aDF*>{#A+MuELv+gDf7xAX9Xyl3;hz>Izw%VoFLgn@`0W&_?eM z99yDq-}qxaW{8cbK15dNX%gtYi(hr;Ujn@}!Bpog591~BUa3_>Z0dP=?O8gFV}-I* z%adX{lBLomsq@gauDtCfd9wl7xh}e_*`=lNwO6MZR=hb8t)jQjP};~@5KojQvBAE` ztumbLj*1~Enb(G(`hiuvP#LfZq`=L3Y;@P=gsx%D$5Qu!L_N)y4BdFcS1T3eA~z zE;ht1VbOQ2Fx9lr?SSLMamfa|jrEEmlJQ2LrrK|=QE#nG*z!#7XzGgB#1LK~#R7li z?VDM#{B_}G zLR@Wf$32JtyOev~8Y{C@+&Bs9g_LMOyU>!X3=~_oE=2lIa5Okajz{G-xSrnTKLM&C z=7`O;fKX+Pclue9desv4B@in{=Fvs#dWI^Wqm7Tth8jPDATQe_xF1=saQaIX_#dDh zXTArp7q@Sv)44L9_XlWxmY0rK7`N@`5ngQj%q9BHqa23yO!4e*6pyWjhSHTK>TS_uEK7ieSYp@rj zhNW@3kds}G-Pv&!5^@$Qa&~sM+I-^YgmLUj?S1!| z`v|Mkmk9wQZ>O|zZ#kovjcm1Zw6wNreKzQZanAZq-jkw=AHHh(3zi+lMj>Ln(L?oz zGp6)DJx1_Ffl+Qsc4UgA#Pu?Z1Wd1DxUQw0sQ|t_wDRz; ztqM>iZ-Tr$!rg-ae7I}C(FVvH^SuqC-anQwQ8el0K6R53=Mv>V^xeBXO^Hal50Yk$ z6OI=_HbL%SFNNb#X)th*U93A622=^X4ShR-P6StS2QhOk2Fj8oX$7C!Gb-hm7y-f& ziADf0b2gBvAqkP6*A#d&(OM6*e76Lq_{X)g;hp8wSER3%6k2__Bkwal(*LlGF9RG# z9$8|)vFSv4Hn2It`ws4XYBP_dldduW6F`$ohT*3BLSBqy#SUH7<-y{N7dQMM(*~Tv z;uRc`B4{t10K!R#%+30#gu7Wc^MQD!rI?^oU_HRk0vT+RySC87fL^qcoyTIYWfWgj ze;S3ueDW7U%qC1~MmBpF2<_?T`fon208454u8mSA$~t_ThRB4cEjM2xYiY@f2xHc+ zPp2^Rr9SCb&khm}B*f8?a+a{*;L!K)W!(3RS=&$QE=PPE0EVSLu)~r>*>(@Q`xyAS zmCbJZ0*)EPs@~?E*A@{Nu|W80ZA7c*-;YQr823`B$%b8=HptfH9RNHvT)AgFT!Lj1 zYdgI_))Xegf|*Mx&>s1QjI8=Yi26i-OD0r5PQPZz>#f<6fp)aG*|2u`^eQz@@8CAP zFHOKm#bI<>9$$0^W;^7&34GU8OHy9!iL4La^Ko$EZv6&Eq0srT=0-Qt{P${G+0XWjw5gFp0bt1JN}M`xV!e4#l_M z7(SE_2$DD-_=rT`08nA5Qc&ZW(-cU_W(_U3L$SitJSxJw)j7GZO`ktW5M(?}$_8Er z-79=yY~#Fqe8s*;pH*VqeJ-VZM-RjTn-9b!db~MQRLXq=uX7oprOtwv07fKusn{J2 z_4aPC2hzuzIQFbKT{+BHLor}}zG@kZ_Df0%hx95;b%Jyh<0;a3kGCKjf!%#LH=kLx zT)XlOh4Ovg2>h~I=`2+!G#%vInn44LvqbEl_{DI)`Y{%)Je;8oi% zWB8aJ0WiJHell@!SlV;jfsvUx87+u;t56lgDbac{p!M*dcn;tn59TXZo=0zrta_f? z;*_XRjevvl2;k2gLxOprnk=e>KSydw-4S#$&`vwf!FkXYNH(JC)2;sflM+_mHXZC* zqlc_tJx;^2a`qmk&y_+4&1A3tGtVg^L|U@KPwRSdBtr#foA`g@m;+CRRp(_NNC0>- z$ChzUAZjR`ovzi_52*Z)NUQABTJ-~OFXPuaf$=Lv%5uJ@tc;tmw_<#Tte^ioS(6-} zlOP+0wust)@;JLHrSx@68wLp#z0Kj)5s6D^1j$?wa05hNW$$$yyT3bN;F!sfO|%rr ziSqG&Ox#@=&mbmp;=li*jW-iK|96$Ojg8%I`S-Q)eQENa+ilbJ($_guK2uOq zX3~W{_oeoCs2f=mI}5;fo%wWc(UlYqjZ8UsPyW`)sabeh;I4P@dd}>>J@uoIOkr2Y zevWsiohvWB3w&^966MJ%L0Ne?d<>s1IW%?N-)zSMSGfp;23g@vQPKO{qUtpZKJ+rV zo|%?icYqV}kn|M~oqlV%v_){^<$U(G41%fFfTF-Sw!{t4fGPxi_(T`!T)W$t& zPM3nI8WZ&orwbj;pBt*2djqab{Z(+6O;4G46%lqdA=*{FYBN=^oIWf94=S~@=%#<7 zJB~hp1*C62+b{Jo%~0WjQH~ws*S)K|2ht-t}FaEXp!P{hT=vL2!R3P7T`XEAnyS3py4cz zG+=H1Z%j#-?Vxq_BxKg+cv z2~Ye1UaZQng>NXT0Ka4*B~>oEVAJRy;5%LDO z0DA2iYU&>OZ|itC!u73H>wUZbQo?2)I2 zE$JJm1#fL`_R1%!rM`(9jE{);f*gID`Q$F?Udw9!Y55TOiLI`siRHeRGWfV5qfalf z%6Yj&*5J(7`?93Fp*XZsn*?=b`oId~6}1?9n1#Ss-FQi;X<_GMKO$w{Wi>%_(i))f z^QkbF+Faz~#>R%Gssemzf$lhNB2@H=GAaHsRJP_=f?4dr2tt5LYd1BFd*!!wiNrDc z`y)LWs%p~Ei6AN-#^b^dU%O$KyWFD25skn5bT?7nettf9%s|w1Po?VxX(&4wr$ib@ zW*~FqrEsUQIJUxd?jji197=?Xbt7x?p4PMkYUgnBHMM;E#>GW<<%#UEY#Sb_SS!3Y z;&fQOfujY&oL_4JR}{zU0!byOI!EHiy6{aImiFosnvX}DLzO*SYa+PR7H(vaa@#3V z9DK=6#{x0l0KJ@yQTp8;by?cN&dqHcvXi5m&=Oeu!XE?gcz416Cv;GrpM$T?^|*||WfnO=H18ycR%mr01L?b^ zMtbtpb9DGgemsE81-oMx)5-h!RVP?oS$Rl)D*#EE6Z%oVywD(5m0B~B3&4W%9G~7O zKsLciqaNeQXkma89pG_Ji&^r1ILHb?aKXIFXzR8xZAy zv!#-c9^+X~h-&FIH#MnR?zmT~7S&?`W6~UxNlaC>BPh5lo+g29=-P`=z+3XBVEI-C zUS1oa+1(z9?sA{}?rZS;_;R#90+~JA`+u_8Mwx+U@DERT#h_4pMc27S9lGL9dh*cx z%LK26y4lpKkNd1PkUuT z;;*K>E^_;Tkm2hs5or=40NrL9^({E sNk2>(NF*f#tyd&Y{(t?aW-jjNWd7?DG5%{x?WD~pE2=BxKQMjsfA6gL&;S4c literal 0 HcmV?d00001 From f0d4758be56fac382fc2350ec308ffb28504f562 Mon Sep 17 00:00:00 2001 From: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> Date: Tue, 5 Jul 2022 20:09:31 -0500 Subject: [PATCH 40/42] [state store ttl] Added metadata.ttlInSeconds (#2583) * initial change Signed-off-by: Hannah Hunter * remove from table Signed-off-by: Hannah Hunter * update title Signed-off-by: Hannah Hunter Co-authored-by: Mark Fussell --- .../state-management/state-store-ttl.md | 6 +++--- daprdocs/content/en/reference/api/state_api.md | 10 ++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/daprdocs/content/en/developing-applications/building-blocks/state-management/state-store-ttl.md b/daprdocs/content/en/developing-applications/building-blocks/state-management/state-store-ttl.md index bb150aa38..f40c723ae 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/state-management/state-store-ttl.md +++ b/daprdocs/content/en/developing-applications/building-blocks/state-management/state-store-ttl.md @@ -1,9 +1,9 @@ --- type: docs -title: "How-To: Set state Time-to-Live (TTL)" -linkTitle: "How-To: Set state TTL" +title: "State Time-to-Live (TTL)" +linkTitle: "State TTL" weight: 500 -description: "Manage state with time-to-live." +description: "Manage state with TTL." --- ## Introduction diff --git a/daprdocs/content/en/reference/api/state_api.md b/daprdocs/content/en/reference/api/state_api.md index 011d4d595..bfb8ea05c 100644 --- a/daprdocs/content/en/reference/api/state_api.md +++ b/daprdocs/content/en/reference/api/state_api.md @@ -82,6 +82,16 @@ Field | Description > **ETag format:** Dapr runtime treats ETags as opaque strings. The exact ETag format is defined by the corresponding data store. +#### Metadata + +Metadata can be sent via query parameters in the request's URL. It must be prefixed with `metadata.`, as shown below. + +Parameter | Description +--------- | ----------- +`metadata.ttlInSeconds` | The number of seconds for the message to expire, as [described here]({{< ref state-store-ttl.md >}}) + +> **TTL:** Only certain state stores support the TTL option, according the [supported state stores]({{< ref supported-state-stores.md >}}). + ### HTTP Response #### Response Codes From a380dcbecc93f86fd53dd20c1f4faed8694a83d4 Mon Sep 17 00:00:00 2001 From: Hannah Hunter <94493363+hhunter-ms@users.noreply.github.com> Date: Wed, 6 Jul 2022 13:23:54 -0500 Subject: [PATCH 41/42] [State Mgmt] Docset refresh (#2541) * initial refresh Signed-off-by: Hannah Hunter * a few more edits Signed-off-by: Hannah Hunter * updates per Mark Signed-off-by: Hannah Hunter Co-authored-by: Mark Fussell --- .../state-management/howto-encrypt-state.md | 52 +++--- .../state-management/howto-get-save-state.md | 155 +++++++++-------- .../state-management/howto-share-state.md | 32 ++-- .../state-management/howto-state-query-api.md | 156 ++++++++++++------ .../howto-stateful-service.md | 69 ++++---- .../query-state-store/_index.md | 2 +- .../query-state-store/query-cosmosdb-store.md | 42 +++-- .../query-state-store/query-redis-store.md | 35 ++-- .../query-sqlserver-store.md | 37 +++-- .../state-management-overview.md | 137 +++++++++------ .../state-management/state-store-ttl.md | 26 ++- 11 files changed, 454 insertions(+), 289 deletions(-) diff --git a/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-encrypt-state.md b/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-encrypt-state.md index bf6df31ee..45aecb525 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-encrypt-state.md +++ b/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-encrypt-state.md @@ -7,18 +7,15 @@ description: "Automatically encrypt state and manage key rotations" --- -## Introduction +Encrypt application state at rest to provide stronger security in enterprise workloads or regulated environments. Dapr offers automatic client-side encryption based on [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) in [Galois/Counter Mode (GCM)](https://en.wikipedia.org/wiki/Galois/Counter_Mode), supporting keys of 128, 192, and 256-bits. -Application state often needs to get encrypted at rest to provide stronger security in enterprise workloads or regulated environments. Dapr offers automatic client side encryption based on [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) in [Galois/Counter Mode (GCM)](https://en.wikipedia.org/wiki/Galois/Counter_Mode), supporting keys of 128, 192, and 256-bits. - -In addition to automatic encryption, Dapr supports primary and secondary encryption keys to make it easier for developers and ops teams to enable a key rotation strategy. -This feature is supported by all Dapr state stores. +In addition to automatic encryption, Dapr supports primary and secondary encryption keys to make it easier for developers and ops teams to enable a key rotation strategy. This feature is supported by all Dapr state stores. The encryption keys are always fetched from a secret, and cannot be supplied as plaintext values on the `metadata` section. ## Enabling automatic encryption -1. Add the following `metadata` section to any Dapr supported state store: +Add the following `metadata` section to any Dapr supported state store: ```yaml metadata: @@ -28,7 +25,7 @@ metadata: key: mykey # key is optional. ``` -For example, this is the full YAML of a Redis encrypted state store +For example, this is the full YAML of a Redis encrypted state store: ```yaml apiVersion: dapr.io/v1alpha1 @@ -49,18 +46,18 @@ spec: key: mykey ``` -You now have a Dapr state store that's configured to fetch the encryption key from a secret named `mysecret`, containing the actual encryption key in a key named `mykey`. +You now have a Dapr state store configured to fetch the encryption key from a secret named `mysecret`, containing the actual encryption key in a key named `mykey`. -The actual encryption key *must* be a valid, hex-encoded encryption key. We recommend using 128-bit encryption keys; 192-bit and 256-bit keys are supported too. Dapr errors and exists if the encryption key is invalid. +The actual encryption key *must* be a valid, hex-encoded encryption key. While 192-bit and 256-bit keys are supported, it's recommended you use 128-bit encryption keys. Dapr errors and exists if the encryption key is invalid. -> As an example, you can generate a random, hex-encoded 128-bit (16-byte) key with: -> -> ```sh -> openssl rand 16 | hexdump -v -e '/1 "%02x"' -> # Result will be similar to "cb321007ad11a9d23f963bff600d58e0" -> ``` +For example, you can generate a random, hex-encoded 128-bit (16-byte) key with: -*Note that the secret store does not have to support keys* +```sh +openssl rand 16 | hexdump -v -e '/1 "%02x"' +# Result will be similar to "cb321007ad11a9d23f963bff600d58e0" +``` + +*Note that the secret store does not have to support keys.* ## Key rotation @@ -78,11 +75,24 @@ metadata: key: mykey2 ``` -When Dapr starts, it will fetch the secrets containing the encryption keys listed in the `metadata` section. Dapr knows which state item has been encrypted with which key automatically, as it appends the `secretKeyRef.name` field to the end of the actual state key. +When Dapr starts, it fetches the secrets containing the encryption keys listed in the `metadata` section. Dapr automatically knows which state item has been encrypted with which key, as it appends the `secretKeyRef.name` field to the end of the actual state key. -To rotate a key, change the `primaryEncryptionKey` to point to a secret containing your new key, and move the old primary encryption key to the `secondaryEncryptionKey`. New data will be encrypted using the new key, and old data that's retrieved will be decrypted using the secondary key. Any updates to data items encrypted using the old key will be re-encrypted using the new key. Note that when you rotate a key, data encrypted with the old key is not automatically re-encrypted unless your application writes it again. If you remove the rotated key (the now-secondary encryption key), you will not be able to access data that was encrypted with that. +To rotate a key, + +1. Change the `primaryEncryptionKey` to point to a secret containing your new key. +1. Move the old primary encryption key to the `secondaryEncryptionKey`. + +New data will be encrypted using the new key, and any retrieved old data will be decrypted using the secondary key. + +Any updates to data items encrypted with the old key will be re-encrypted using the new key. + +{{% alert title="Note" color="primary" %}} +when you rotate a key, data encrypted with the old key is not automatically re-encrypted unless your application writes it again. If you remove the rotated key (the now-secondary encryption key), you will not be able to access data that was encrypted with that. + +{{% /alert %}} ## Related links - - [Security overview]({{< ref "security-concept.md" >}}) - - [State store query API implementation guide](https://github.com/dapr/components-contrib/blob/master/state/Readme.md#implementing-state-query-api) - - [State store components]({{< ref "supported-state-stores.md" >}}) + +- [Security overview]({{< ref "security-concept.md" >}}) +- [State store query API implementation guide](https://github.com/dapr/components-contrib/blob/master/state/Readme.md#implementing-state-query-api) +- [State store components]({{< ref "supported-state-stores.md" >}}) diff --git a/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-get-save-state.md b/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-get-save-state.md index fce19c3ff..d665037fb 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-get-save-state.md +++ b/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-get-save-state.md @@ -6,26 +6,17 @@ weight: 200 description: "Use key value pairs to persist a state" --- -## Introduction +State management is one of the most common needs of any new, legacy, monolith, or microservice application. Dealing with and testing different database libraries and handling retries and faults can be both difficult and time consuming. -State management is one of the most common needs of any application: new or legacy, monolith or microservice. -Dealing with different databases libraries, testing them, handling retries and faults can be time consuming and hard. +In this guide, you'll learn the basics of using the key/value state API to allow an application to save, get, and delete state. -Dapr provides state management capabilities that include consistency and concurrency options. -In this guide we'll start of with the basics: Using the key/value state API to allow an application to save, get and delete state. +## Example -## Pre-requisites - -- [Dapr CLI]({{< ref install-dapr-cli.md >}}) -- Initialized [Dapr environment]({{< ref install-dapr-selfhost.md >}}) - -## Example: - -The below code examples loosely describe an application that processes orders. In the examples, there is an order processing service which has a Dapr sidecar. The order processing service uses Dapr to store state in a Redis state store. +The code example below _loosely_ describes an application that processes orders with an order processing service which has a Dapr sidecar. The order processing service uses Dapr to store state in a Redis state store. Diagram showing state management of example service -## Step 1: Setup a state store +## Set up a state store A state store component represents a resource that Dapr uses to communicate with a database. @@ -34,14 +25,19 @@ For the purpose of this guide we'll use a Redis state store, but any state store {{< tabs "Self-Hosted (CLI)" Kubernetes>}} {{% codetab %}} -When using `dapr init` in Standalone mode, the Dapr CLI automatically provisions a state store (Redis) and creates the relevant YAML in a `components` directory, which for Linux/MacOS is `$HOME/.dapr/components` and for Windows is `%USERPROFILE%\.dapr\components` -To optionally change the state store being used, replace the YAML file `statestore.yaml` under `/components` with the file of your choice. +When you run `dapr init` in self-hosted mode, Dapr creates a default Redis `statestore.yaml` and runs a Redis state store on your local machine, located: + +- On Windows, under `%UserProfile%\.dapr\components\statestore.yaml` +- On Linux/MacOS, under `~/.dapr/components/statestore.yaml` + +With the `statestore.yaml` component, you can easily swap out underlying components without application code changes. + {{% /codetab %}} {{% codetab %}} -To deploy this into a Kubernetes cluster, fill in the `metadata` connection details of your [desired statestore component]({{< ref supported-state-stores >}}) in the yaml below, save as `statestore.yaml`, and run `kubectl apply -f statestore.yaml`. +To deploy this into a Kubernetes cluster, fill in the `metadata` connection details of your [state store component]({{< ref supported-state-stores >}}) in the YAML below, save as `statestore.yaml`, and run `kubectl apply -f statestore.yaml`. ```yaml apiVersion: dapr.io/v1alpha1 @@ -58,21 +54,20 @@ spec: - name: redisPassword value: "" ``` -See the instructions [here]({{< ref "setup-state-store" >}}) on how to setup different state stores on Kubernetes. + +See [how to setup different state stores on Kubernetes]({{< ref "setup-state-store" >}}). {{% /codetab %}} {{< /tabs >}} -## Step 2: Save and retrieve a single state - -The following example shows how to save and retrieve a single key/value pair using the Dapr state building block. - -{{% alert title="Note" color="warning" %}} -It is important to set an app-id, as the state keys are prefixed with this value. If you don't set it one is generated for you at runtime, and the next time you run the command a new one will be generated and you will no longer be able to access previously saved state. +{{% alert title="Important" color="warning" %}} +Set an `app-id`, as the state keys are prefixed with this value. If you don't set an `app-id`, one is generated for you at runtime. The next time you run the command, a new `app-id` is generated and you will no longer have access to the previously saved state. {{% /alert %}} -Below are code examples that leverage Dapr SDKs for saving and retrieving a single state. +## Save and retrieve a single state + +The following example shows how to save and retrieve a single key/value pair using the Dapr state management API. {{< tabs Dotnet Java Python Go Javascript "HTTP API (Bash)" "HTTP API (PowerShell)">}} @@ -115,7 +110,7 @@ namespace EventService } ``` -Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application: +To launch a Dapr sidecar for the above example application, run a command similar to the following: ```bash dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 dotnet run @@ -123,7 +118,6 @@ dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-g {{% /codetab %}} - {{% codetab %}} ```java @@ -164,7 +158,7 @@ public class OrderProcessingServiceApplication { } ``` -Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application: +To launch a Dapr sidecar for the above example application, run a command similar to the following: ```bash dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 mvn spring-boot:run @@ -172,7 +166,6 @@ dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-g {{% /codetab %}} - {{% codetab %}} ```python @@ -198,7 +191,7 @@ while True: logging.info('Result after get: ' + result.data.decode('utf-8')) ``` -Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application: +To launch a Dapr sidecar for the above example application, run a command similar to the following: ```bash dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 -- python3 OrderProcessingService.py @@ -206,7 +199,6 @@ dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-g {{% /codetab %}} - {{% codetab %}} ```go @@ -247,7 +239,7 @@ func main() { } ``` -Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application: +To launch a Dapr sidecar for the above example application, run a command similar to the following: ```bash dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 go run OrderProcessingService.go @@ -255,7 +247,6 @@ dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-g {{% /codetab %}} - {{% codetab %}} ```javascript @@ -300,7 +291,7 @@ function sleep(ms) { main(); ``` -Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application: +To launch a Dapr sidecar for the above example application, run a command similar to the following: ```bash dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 npm start @@ -308,41 +299,46 @@ dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-g {{% /codetab %}} - {{% codetab %}} -Begin by launching a Dapr sidecar: + +Launch a Dapr sidecar: ```bash dapr run --app-id orderprocessing --dapr-http-port 3601 ``` -Then in a separate terminal save a key/value pair into your statestore: +In a separate terminal, save a key/value pair into your statestore: + ```bash curl -X POST -H "Content-Type: application/json" -d '[{ "key": "order_1", "value": "250"}]' http://localhost:3601/v1.0/state/statestore ``` Now get the state you just saved: + ```bash curl http://localhost:3601/v1.0/state/statestore/order_1 ``` Restart your sidecar and try retrieving state again to observe that state persists separately from the app. + {{% /codetab %}} {{% codetab %}} -Begin by launching a Dapr sidecar: +Launch a Dapr sidecar: ```bash dapr --app-id orderprocessing --dapr-http-port 3601 run ``` -Then in a separate terminal save a key/value pair into your statestore: +In a separate terminal, save a key/value pair into your statestore: + ```powershell Invoke-RestMethod -Method Post -ContentType 'application/json' -Body '[{"key": "order_1", "value": "250"}]' -Uri 'http://localhost:3601/v1.0/state/statestore' ``` Now get the state you just saved: + ```powershell Invoke-RestMethod -Uri 'http://localhost:3601/v1.0/state/statestore/order_1' ``` @@ -353,8 +349,7 @@ Restart your sidecar and try retrieving state again to observe that state persis {{< /tabs >}} - -## Step 3: Delete state +## Delete state Below are code examples that leverage Dapr SDKs for deleting the state. @@ -382,7 +377,7 @@ namespace EventService } ``` -Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application: +To launch a Dapr sidecar for the above example application, run a command similar to the following: ```bash dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 dotnet run @@ -390,7 +385,6 @@ dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-g {{% /codetab %}} - {{% codetab %}} ```java @@ -413,7 +407,7 @@ public class OrderProcessingServiceApplication { } ``` -Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application: +To launch a Dapr sidecar for the above example application, run a command similar to the following: ```bash dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 mvn spring-boot:run @@ -421,7 +415,6 @@ dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-g {{% /codetab %}} - {{% codetab %}} ```python @@ -437,7 +430,7 @@ with DaprClient() as client: client.delete_state(store_name=DAPR_STORE_NAME, key="order_1") ``` -Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application: +To launch a Dapr sidecar for the above example application, run a command similar to the following: ```bash dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 -- python3 OrderProcessingService.py @@ -445,7 +438,6 @@ dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-g {{% /codetab %}} - {{% codetab %}} ```go @@ -473,7 +465,7 @@ func main() { } ``` -Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application: +To launch a Dapr sidecar for the above example application, run a command similar to the following: ```bash dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 go run OrderProcessingService.go @@ -481,7 +473,6 @@ dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-g {{% /codetab %}} - {{% codetab %}} ```javascript @@ -500,7 +491,7 @@ var main = function() { main(); ``` -Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application: +To launch a Dapr sidecar for the above example application, run a command similar to the following: ```bash dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 npm start @@ -509,24 +500,32 @@ dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-g {{% /codetab %}} {{% codetab %}} -With the same Dapr instance running from above run: + +With the same Dapr instance running from above, run: + ```bash curl -X DELETE 'http://localhost:3601/v1.0/state/statestore/order_1' ``` -Try getting state again and note that no value is returned. + +Try getting state again. Note that no value is returned. + {{% /codetab %}} {{% codetab %}} -With the same Dapr instance running from above run: + +With the same Dapr instance running from above, run: + ```powershell Invoke-RestMethod -Method Delete -Uri 'http://localhost:3601/v1.0/state/statestore/order_1' ``` -Try getting state again and note that no value is returned. + +Try getting state again. Note that no value is returned. + {{% /codetab %}} {{< /tabs >}} -## Step 4: Save and retrieve multiple states +## Save and retrieve multiple states Below are code examples that leverage Dapr SDKs for saving and retrieving multiple states. @@ -553,7 +552,7 @@ namespace EventService } ``` -Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application: +To launch a Dapr sidecar for the above example application, run a command similar to the following: ```bash dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 dotnet run @@ -586,7 +585,7 @@ public class OrderProcessingServiceApplication { } ``` -Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application: +To launch a Dapr sidecar for the above example application, run a command similar to the following: ```bash dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 mvn spring-boot:run @@ -612,7 +611,7 @@ with DaprClient() as client: logging.info('Result after get bulk: ' + str(result)) ``` -Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application: +To launch a Dapr sidecar for the above example application, run a command similar to the following: ```bash dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 -- python3 OrderProcessingService.py @@ -649,7 +648,7 @@ var main = function() { main(); ``` -Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application: +To launch a Dapr sidecar for the above example application, run a command similar to the following: ```bash dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 npm start @@ -658,24 +657,31 @@ dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-g {{% /codetab %}} {{% codetab %}} -With the same Dapr instance running from above save two key/value pairs into your statestore: + +With the same Dapr instance running from above, save two key/value pairs into your statestore: + ```bash curl -X POST -H "Content-Type: application/json" -d '[{ "key": "order_1", "value": "250"}, { "key": "order_2", "value": "550"}]' http://localhost:3601/v1.0/state/statestore ``` Now get the states you just saved: + ```bash curl -X POST -H "Content-Type: application/json" -d '{"keys":["order_1", "order_2"]}' http://localhost:3601/v1.0/state/statestore/bulk ``` + {{% /codetab %}} {{% codetab %}} -With the same Dapr instance running from above save two key/value pairs into your statestore: + +With the same Dapr instance running from above, save two key/value pairs into your statestore: + ```powershell Invoke-RestMethod -Method Post -ContentType 'application/json' -Body '[{ "key": "order_1", "value": "250"}, { "key": "order_2", "value": "550"}]' -Uri 'http://localhost:3601/v1.0/state/statestore' ``` Now get the states you just saved: + ```powershell Invoke-RestMethod -Method Post -ContentType 'application/json' -Body '{"keys":["order_1", "order_2"]}' -Uri 'http://localhost:3601/v1.0/state/statestore/bulk' ``` @@ -684,10 +690,10 @@ Invoke-RestMethod -Method Post -ContentType 'application/json' -Body '{"keys":[" {{< /tabs >}} -## Step 5: Perform state transactions +## Perform state transactions -{{% alert title="Note" color="warning" %}} -State transactions require a state store that supports multi-item transactions. Visit the [supported state stores page]({{< ref supported-state-stores >}}) page for a full list. Note that the default Redis container created in a self-hosted environment supports them. +{{% alert title="Note" color="primary" %}} +State transactions require a state store that supports multi-item transactions. See the [supported state stores page]({{< ref supported-state-stores >}}) for a full list. {{% /alert %}} Below are code examples that leverage Dapr SDKs for performing state transactions. @@ -738,7 +744,7 @@ namespace EventService } ``` -Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application: +To launch a Dapr sidecar for the above example application, run a command similar to the following: ```bash dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 dotnet run @@ -746,7 +752,6 @@ dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-g {{% /codetab %}} - {{% codetab %}} ```java @@ -792,7 +797,7 @@ public class OrderProcessingServiceApplication { } ``` -Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application: +To launch a Dapr sidecar for the above example application, run a command similar to the following: ```bash dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 mvn spring-boot:run @@ -838,7 +843,7 @@ while True: logging.info('Result: ' + str(result)) ``` -Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application: +To launch a Dapr sidecar for the above example application, run a command similar to the following: ```bash dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 -- python3 OrderProcessingService.py @@ -846,7 +851,6 @@ dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-g {{% /codetab %}} - {{% codetab %}} ```javascript @@ -894,7 +898,7 @@ function sleep(ms) { main(); ``` -Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application: +To launch a Dapr sidecar for the above example application, run a command similar to the following: ```bash dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 npm start @@ -903,24 +907,31 @@ dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-g {{% /codetab %}} {{% codetab %}} -With the same Dapr instance running from above perform two state transactions: + +With the same Dapr instance running from above, perform two state transactions: + ```bash curl -X POST -H "Content-Type: application/json" -d '{"operations": [{"operation":"upsert", "request": {"key": "order_1", "value": "250"}}, {"operation":"delete", "request": {"key": "order_2"}}]}' http://localhost:3601/v1.0/state/statestore/transaction ``` Now see the results of your state transactions: + ```bash curl -X POST -H "Content-Type: application/json" -d '{"keys":["order_1", "order_2"]}' http://localhost:3601/v1.0/state/statestore/bulk ``` + {{% /codetab %}} {{% codetab %}} -With the same Dapr instance running from above save two key/value pairs into your statestore: + +With the same Dapr instance running from above, save two key/value pairs into your statestore: + ```powershell Invoke-RestMethod -Method Post -ContentType 'application/json' -Body '{"operations": [{"operation":"upsert", "request": {"key": "order_1", "value": "250"}}, {"operation":"delete", "request": {"key": "order_2"}}]}' -Uri 'http://localhost:3601/v1.0/state/statestore' ``` Now see the results of your state transactions: + ```powershell Invoke-RestMethod -Method Post -ContentType 'application/json' -Body '{"keys":["order_1", "order_2"]}' -Uri 'http://localhost:3601/v1.0/state/statestore/bulk' ``` diff --git a/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-share-state.md b/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-share-state.md index bfe44dcfe..27d5b1d26 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-share-state.md +++ b/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-share-state.md @@ -3,22 +3,25 @@ type: docs title: "How-To: Share state between applications" linkTitle: "How-To: Share state between applications" weight: 400 -description: "Choose different strategies for sharing state between different applications" +description: "Learn the strategies for sharing state between different applications" --- -## Introduction +Dapr provides different ways to share state between applications. -Dapr offers developers different ways to share state between applications. +Different architectures might have different needs when it comes to sharing state. In one scenario, you may want to: -Different architectures might have different needs when it comes to sharing state. For example, in one scenario you may want to encapsulate all state within a given application and have Dapr manage the access for you. In a different scenario, you may need to have two applications working on the same state be able to get and save the same keys. +- Encapsulate all state within a given application +- Have Dapr manage the access for you + +In a different scenario, you may need two applications working on the same state to get and save the same keys. To enable state sharing, Dapr supports the following key prefixes strategies: -* **`appid`** - This is the default strategy. the `appid` prefix allows state to be managed only by the app with the specified `appid`. All state keys will be prefixed with the `appid`, and are scoped for the application. - -* **`name`** - This setting uses the name of the state store component as the prefix. Multiple applications can share the same state for a given state store. - -* **`none`** - This setting uses no prefixing. Multiple applications share state across different state stores. +| Key prefixes | Description | +| ------------ | ----------- | +| `appid` | The default strategy allowing you to manage state only by the app with the specified `appid`. All state keys will be prefixed with the `appid`, and are scoped for the application. | +| `name` | Uses the name of the state store component as the prefix. Multiple applications can share the same state for a given state store. | +| `none` | Uses no prefixing. Multiple applications share state across different state stores. | ## Specifying a state prefix strategy @@ -40,11 +43,11 @@ spec: ## Examples -The following examples will show you how state retrieval looks like with each of the supported prefix strategies: +The following examples demonstrate what state retrieval looks like with each of the supported prefix strategies. ### `appid` (default) -A Dapr application with app id `myApp` is saving state into a state store named `redis`: +In the example below, a Dapr application with app id `myApp` is saving state into a state store named `redis`: ```shell curl -X POST http://localhost:3500/v1.0/state/redis \ @@ -61,7 +64,7 @@ The key will be saved as `myApp||darth`. ### `name` -A Dapr application with app id `myApp` is saving state into a state store named `redis`: +In the example below, a Dapr application with app id `myApp` is saving state into a state store named `redis`: ```shell curl -X POST http://localhost:3500/v1.0/state/redis \ @@ -78,7 +81,7 @@ The key will be saved as `redis||darth`. ### `none` -A Dapr application with app id `myApp` is saving state into a state store named `redis`: +In the example below, a Dapr application with app id `myApp` is saving state into a state store named `redis`: ```shell curl -X POST http://localhost:3500/v1.0/state/redis \ @@ -91,5 +94,4 @@ curl -X POST http://localhost:3500/v1.0/state/redis \ ]' ``` -The key will be saved as `darth`. - +The key will be saved as `darth`. \ No newline at end of file diff --git a/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-state-query-api.md b/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-state-query-api.md index 773833269..85e52a3aa 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-state-query-api.md +++ b/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-state-query-api.md @@ -3,36 +3,28 @@ type: docs title: "How-To: Query state" linkTitle: "How-To: Query state" weight: 250 -description: "API for querying state stores" +description: "Use the Query API for querying state stores" --- {{% alert title="alpha" color="warning" %}} The state query API is in **alpha** stage. {{% /alert %}} -## Introduction +With the state query API, you can retrieve, filter, and sort the key/value data stored in state store components. The query API is not a replacement for a complete query language. -The state query API provides a way of querying the key/value data stored in state store components. This query API is not a replacement for a complete query language, and is focused on retrieving, filtering and sorting key/value data that you have saved through the state management APIs. - -Even though the state store is a key/value store, the `value` might be a JSON document with its own hierarchy, keys, and values. -The query API allows you to use those keys and values to retrive corresponding documents. - -### Limitations -The state query API has the following limitations: - - - The API does not support querying of actor state stored in a state store. For that you need to use the query API for the specific database. See [querying actor state]({{< ref "state-management-overview.md#querying-actor-state" >}}). - - The API does not work with Dapr [encrypted state stores]({{}}) capability. Since the encryption is done by the Dapr runtime and stored as encrypted data, then this effectively prevents server side querying. - - - -You can find additional information in the [related links]({{< ref "#related-links" >}}) section. +Even though the state store is a key/value store, the `value` might be a JSON document with its own hierarchy, keys, and values. The query API allows you to use those keys/values to retrieve corresponding documents. ## Querying the state -You submit query requests via HTTP POST/PUT or gRPC. -The body of the request is the JSON map with 3 entries: `filter`, `sort`, and `page`. +Submit query requests via HTTP POST/PUT or gRPC. The body of the request is the JSON map with 3 _optional_ entries: -The `filter` is an optional section. It specifies the query conditions in the form of a tree, where each node represents either unary or multi-operand operation. +- `filter` +- `sort` +- `page` + +### `filter` + +The `filter` specifies the query conditions in the form of a tree, where each node represents either unary or multi-operand operation. The following operations are supported: @@ -43,7 +35,8 @@ The following operations are supported: | `AND` | []operation | operation[0] AND operation[1] AND ... AND operation[n] | | `OR` | []operation | operation[0] OR operation[1] OR ... OR operation[n] | -The `key` in the operand is similar to the JSONPath notation. Each dot in the key indicates a nested JSON structure. Consider for example this structure: +The `key` in the operand is similar to the JSONPath notation. Each dot in the key indicates a nested JSON structure. For example, consider this structure: + ```json { "shape": { @@ -59,53 +52,72 @@ The `key` in the operand is similar to the JSONPath notation. Each dot in the ke } } ``` -If you want to compare the value of the color code, the key will be `shape.color.code` -If `filter` section is omitted, the query returns all entries. +To compare the value of the color code, the key will be `shape.color.code`. -The `sort` is an optional section and is an ordered array of `key:order` pairs, where `key` is a key in the state store, and the `order` is an optional string indicating sorting order: `"ASC"` for ascending and `"DESC"` for descending. If omitted, ascending order is the default. +If the `filter` section is omitted, the query returns all entries. -The `page` is an optional section containing `limit` and `token` parameters. `limit` sets the page size. `token` is an iteration token returned by the component, and is used in subsequent queries. +### `sort` -For some background understanding, this query request is translated into the native query language and executed by the state store component. +The `sort` is an ordered array of `key:order` pairs, where: + +- `key` is a key in the state store +- `order` is an optional string indicating sorting order: + - `"ASC"` for ascending + - `"DESC"` for descending + If omitted, ascending order is the default. + +### `page` + +The `page` contains `limit` and `token` parameters. + +- `limit` sets the page size. +- `token` is an iteration token returned by the component, used in subsequent queries. + +Behind the scenes, this query request is translated into the native query language and executed by the state store component. ## Example data and query -Let's look at some real examples, starting with simple and progressing towards more complex ones. +Let's look at some real examples, ranging from simple to complex. -As a dataset, let's consider a [collection of with employee records](../query-api-examples/dataset.json) containing employee ID, organization, state, and city. -Notice that this dataset is an array of key/value pairs where `key` is the unique ID, and the `value` is the JSON object with employee record. -To better illustrate functionality, let's have organization name (org) and employee ID (id) as a nested JSON person object. +As a dataset, consider a [collection of employee records](../query-api-examples/dataset.json) containing employee ID, organization, state, and city. Notice that this dataset is an array of key/value pairs, where: + +- `key` is the unique ID +- `value` is the JSON object with employee record. + +To better illustrate functionality, organization name (org) and employee ID (id) are a nested JSON person object. + +Get started by creating an instance of MongoDB, which is your state store. -First, you need to create an instance of MongoDB, which is your state store. ```bash docker run -d --rm -p 27017:27017 --name mongodb mongo:5 ``` -Next is to start a Dapr application. Refer to this [component configuration file](../query-api-examples/components/mongodb/mongodb.yml), which instructs Dapr to use MongoDB as its state store. +Next, start a Dapr application. Refer to the [component configuration file](../query-api-examples/components/mongodb/mongodb.yml), which instructs Dapr to use MongoDB as its state store. + ```bash dapr run --app-id demo --dapr-http-port 3500 --components-path query-api-examples/components/mongodb ``` -Now populate the state store with the employee dataset, so you can then query it later. +Populate the state store with the employee dataset, so you can query it later. + ```bash curl -X POST -H "Content-Type: application/json" -d @query-api-examples/dataset.json http://localhost:3500/v1.0/state/statestore ``` -Once populated, you can examine the data in the state store. The image below a section of the MongoDB UI displaying employee records. -
- Sample dataset -
+Once populated, you can examine the data in the state store. In the image below, a section of the MongoDB UI displays employee records. + +Sample dataset Each entry has the `_id` member as a concatenated object key, and the `value` member containing the JSON record. The query API allows you to select records from this JSON structure. -Now you can run the queries. +Now you can run the example queries. ### Example 1 -First, let's find all employees in the state of California and sort them by their employee ID in descending order. +First, find all employees in the state of California and sort them by their employee ID in descending order. This is the [query](../query-api-examples/query1.json): ```json @@ -123,6 +135,7 @@ This is the [query](../query-api-examples/query1.json): ``` An equivalent of this query in SQL is: + ```sql SELECT * FROM c WHERE state = "CA" @@ -131,20 +144,29 @@ ORDER BY ``` Execute the query with the following command: + {{< tabs "HTTP API (Bash)" "HTTP API (PowerShell)" >}} + {{% codetab %}} + ```bash curl -s -X POST -H "Content-Type: application/json" -d @query-api-examples/query1.json http://localhost:3500/v1.0-alpha1/state/statestore/query | jq . ``` + {{% /codetab %}} + {{% codetab %}} + ```powershell Invoke-RestMethod -Method Post -ContentType 'application/json' -InFile query-api-examples/query1.json -Uri 'http://localhost:3500/v1.0-alpha1/state/statestore/query' ``` + {{% /codetab %}} + {{< /tabs >}} The query result is an array of matching key/value pairs in the requested order: + ```json { "results": [ @@ -202,9 +224,10 @@ The query result is an array of matching key/value pairs in the requested order: ### Example 2 -Let's now find all employees from the "Dev Ops" and "Hardware" organizations. +Now, find all employees from the "Dev Ops" and "Hardware" organizations. This is the [query](../query-api-examples/query2.json): + ```json { "filter": { @@ -214,34 +237,44 @@ This is the [query](../query-api-examples/query2.json): ``` An equivalent of this query in SQL is: + ```sql SELECT * FROM c WHERE person.org IN ("Dev Ops", "Hardware") ``` Execute the query with the following command: + {{< tabs "HTTP API (Bash)" "HTTP API (PowerShell)" >}} + {{% codetab %}} + ```bash curl -s -X POST -H "Content-Type: application/json" -d @query-api-examples/query2.json http://localhost:3500/v1.0-alpha1/state/statestore/query | jq . ``` + {{% /codetab %}} + {{% codetab %}} + ```powershell Invoke-RestMethod -Method Post -ContentType 'application/json' -InFile query-api-examples/query2.json -Uri 'http://localhost:3500/v1.0-alpha1/state/statestore/query' ``` + {{% /codetab %}} + {{< /tabs >}} Similar to the previous example, the result is an array of matching key/value pairs. ### Example 3 -In this example let's find all employees from the "Dev Ops" department -and those employees from the "Finance" departing residing in the states of Washington and California. +In this example, find: -In addition, let's sort the results first by state in descending alphabetical order, and then by employee ID in ascending order. -Also, let's process up to 3 records at a time. +- All employees from the "Dev Ops" department. +- Employees from the "Finance" departing residing in the states of Washington and California. + +In addition, sort the results first by state in descending alphabetical order, then by employee ID in ascending order. Let's process up to 3 records at a time. This is the [query](../query-api-examples/query3.json): @@ -280,6 +313,7 @@ This is the [query](../query-api-examples/query3.json): ``` An equivalent of this query in SQL is: + ```sql SELECT * FROM c WHERE person.org = "Dev Ops" OR @@ -291,20 +325,29 @@ LIMIT 3 ``` Execute the query with the following command: + {{< tabs "HTTP API (Bash)" "HTTP API (PowerShell)" >}} + {{% codetab %}} + ```bash curl -s -X POST -H "Content-Type: application/json" -d @query-api-examples/query3.json http://localhost:3500/v1.0-alpha1/state/statestore/query | jq . ``` + {{% /codetab %}} + {{% codetab %}} + ```powershell Invoke-RestMethod -Method Post -ContentType 'application/json' -InFile query-api-examples/query3.json -Uri 'http://localhost:3500/v1.0-alpha1/state/statestore/query' ``` + {{% /codetab %}} + {{< /tabs >}} Upon successful execution, the state store returns a JSON object with a list of matching records and the pagination token: + ```json { "results": [ @@ -387,19 +430,27 @@ The pagination token is used "as is" in the [subsequent query](../query-api-exam ``` {{< tabs "HTTP API (Bash)" "HTTP API (PowerShell)" >}} + {{% codetab %}} + ```bash curl -s -X POST -H "Content-Type: application/json" -d @query-api-examples/query3-token.json http://localhost:3500/v1.0-alpha1/state/statestore/query | jq . ``` + {{% /codetab %}} + {{% codetab %}} + ```powershell Invoke-RestMethod -Method Post -ContentType 'application/json' -InFile query-api-examples/query3-token.json -Uri 'http://localhost:3500/v1.0-alpha1/state/statestore/query' ``` + {{% /codetab %}} + {{< /tabs >}} And the result of this query is: + ```json { "results": [ @@ -443,10 +494,21 @@ And the result of this query is: "token": "6" } ``` + That way you can update the pagination token in the query and iterate through the results until no more records are returned. +## Limitations + +The state query API has the following limitations: + +- To query actor states stored in a state store, you need to use the query API for the specific database. See [querying actor state]({{< ref "state-management-overview.md#querying-actor-state" >}}). +- The API does not work with Dapr [encrypted state stores]({{< ref howto-encrypt-state >}}) capability. Since the encryption is done by the Dapr runtime and stored as encrypted data, then this effectively prevents server side querying. + +You can find additional information in the [related links]({{< ref "#related-links" >}}) section. + ## Related links - - [Query API reference ]({{< ref "state_api.md#state-query" >}}) - - [State store components with those that implement query support]({{< ref supported-state-stores.md >}}) - - [State store query API implementation guide](https://github.com/dapr/components-contrib/blob/master/state/Readme.md#implementing-state-query-api) - - [Querying Redis state store]({{< ref "setup-redis.md#querying-json-objects" >}}) + +- Refer to the [query API reference]({{< ref "state_api.md#state-query" >}}). +- See the [state store components that implement query support]({{< ref supported-state-stores.md >}}). +- View the [state store query API implementation guide](https://github.com/dapr/components-contrib/blob/master/state/Readme.md#implementing-state-query-api). +- See how to [query Redis state store]({{< ref "setup-redis.md#querying-json-objects" >}}). diff --git a/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-stateful-service.md b/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-stateful-service.md index e53a50108..8ef21d898 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-stateful-service.md +++ b/daprdocs/content/en/developing-applications/building-blocks/state-management/howto-stateful-service.md @@ -6,39 +6,41 @@ weight: 300 description: "Use state management with a scaled, replicated service" --- -In this article you'll learn how you can create a stateful service which can be horizontally scaled, using opt-in concurrency and consistency models. +In this article, you'll learn how to create a stateful service which can be horizontally scaled, using opt-in concurrency and consistency models. Consuming the state management API frees developers from difficult state coordination, conflict resolution, and failure handling. -This frees developers from difficult state coordination, conflict resolution and failure handling, and allows them instead to consume these capabilities as APIs from Dapr. - -## Setup a state store +## Set up a state store A state store component represents a resource that Dapr uses to communicate with a database. -For the purpose of this guide, we'll use a Redis state store. - -See a list of supported state stores [here]({{< ref supported-state-stores >}}) +For the purpose of this guide, we'll use the default Redis state store. ### Using the Dapr CLI -The Dapr CLI automatically provisions a state store (Redis) and creates the relevant YAML when running your app with `dapr run`. -To change the state store being used, replace the YAML under `/components` with the file of your choice. +When you run `dapr init` in self-hosted mode, Dapr creates a default Redis `statestore.yaml` and runs a Redis state store on your local machine, located: + +- On Windows, under `%UserProfile%\.dapr\components\statestore.yaml` +- On Linux/MacOS, under `~/.dapr/components/statestore.yaml` + +With the `statestore.yaml` component, you can easily swap out underlying components without application code changes. + +See a [list of supported state stores]({{< ref supported-state-stores >}}). ### Kubernetes -See the instructions [here]({{}}) on how to setup different state stores on Kubernetes. +See [how to setup different state stores on Kubernetes]({{}}). -## Strong and Eventual consistency +## Strong and eventual consistency -Using strong consistency, Dapr will make sure the underlying state store returns the response once the data has been written to all replicas or received an ack from a quorum before writing or deleting state. +Using strong consistency, Dapr makes sure that the underlying state store: -For get requests, Dapr will make sure the store returns the most up to date data consistently among replicas. -The default is eventual consistency, unless specified otherwise in the request to the state API. +- Returns the response once the data has been written to all replicas. +- Receives an ACK from a quorum before writing or deleting state. -The following examples illustrates using strong consistency: +For get requests, Dapr ensures the store returns the most up-to-date data consistently among replicas. The default is eventual consistency, unless specified otherwise in the request to the state API. + +The following examples illustrate how to save, get, and delete state using strong consistency. The example is written in Python, but is applicable to any programming language. ### Saving state -*The following example is written in Python, but is applicable to any programming language* - ```python import requests import json @@ -51,8 +53,6 @@ response = requests.post(dapr_state_url, json=stateReq) ### Getting state -*The following example is written in Python, but is applicable to any programming language* - ```python import requests import json @@ -65,8 +65,6 @@ print(response.headers['ETag']) ### Deleting state -*The following example is written in Python, but is applicable to any programming language* - ```python import requests import json @@ -76,24 +74,31 @@ dapr_state_url = "http://localhost:3500/v1.0/state/{}".format(store_name) response = requests.delete(dapr_state_url + "/key1", headers={"consistency":"strong"}) ``` -Last-write concurrency is the default concurrency mode if the `concurrency` option is not specified. +If the `concurrency` option hasn't been specified, the default is last-write concurrency mode. -## First-write-wins and Last-write-wins +## First-write-wins and last-write-wins -Dapr allows developers to opt-in for two common concurrency patterns when working with data stores: First-write-wins and Last-write-wins. -First-Write-Wins is useful in situations where you have multiple instances of an application, all writing to the same key concurrently. +Dapr allows developers to opt-in for two common concurrency patterns when working with data stores: -The default mode for Dapr is Last-write-wins. +- **First-write-wins**: useful in situations where you have multiple instances of an application, all writing to the same key concurrently. +- **Last-write-wins**: Default mode for Dapr. -Dapr uses version numbers to determine whether a specific key has been updated. Clients retain the version number when reading the data for a key and then use the version number during updates such as writes and deletes. If the version information has changed since the client retrieved, an error is thrown, which then requires the client to perform a read again to get the latest version information and state. +Dapr uses version numbers to determine whether a specific key has been updated. You can: -Dapr utilizes ETags to determine the state's version number. ETags are returned from state requests in an `ETag` header. +1. Retain the version number when reading the data for a key. +1. Use the version number during updates such as writes and deletes. -Using ETags, clients know that a resource has been updated since the last time they checked by erroring when there's an ETag mismatch. +If the version information has changed since the version number was retrieved, an error is thrown, requiring you to perform another read to get the latest version information and state. -The following example shows how to get an ETag, and then use it to save state and then delete the state: +Dapr utilizes ETags to determine the state's version number. ETags are returned from state requests in an `ETag` header. Using ETags, your application knows that a resource has been updated since the last time they checked by erroring during an ETag mismatch. -*The following example is written in Python, but is applicable to any programming language* +The following example shows how to: + +- Get an ETag. +- Use the ETag to save state. +- Delete the state. + +The following example is written in Python, but is applicable to any programming language. ```python import requests @@ -111,7 +116,7 @@ response = requests.delete(dapr_state_url + "/key1", headers={"If-Match": "{}".f ### Handling version mismatch failures -In this example, we'll see how to retry a save state operation when the version has changed: +In the following example, you'll see how to retry a save state operation when the version has changed: ```python import requests diff --git a/daprdocs/content/en/developing-applications/building-blocks/state-management/query-state-store/_index.md b/daprdocs/content/en/developing-applications/building-blocks/state-management/query-state-store/_index.md index 665334824..3641b54fc 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/state-management/query-state-store/_index.md +++ b/daprdocs/content/en/developing-applications/building-blocks/state-management/query-state-store/_index.md @@ -6,4 +6,4 @@ weight: 500 description: "Guides for working with specific backend states stores" --- -Explore the **Operations** section to see a list of [supported state stores]({{}}) and how to setup [state store components]({{}}). \ No newline at end of file +Explore the **Operations** section to see a list of [supported state stores]({{< ref supported-state-stores.md >}}) and how to setup [state store components]({{< ref setup-state-store.md >}}). \ No newline at end of file diff --git a/daprdocs/content/en/developing-applications/building-blocks/state-management/query-state-store/query-cosmosdb-store.md b/daprdocs/content/en/developing-applications/building-blocks/state-management/query-state-store/query-cosmosdb-store.md index a181905c8..3774c9fae 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/state-management/query-state-store/query-cosmosdb-store.md +++ b/daprdocs/content/en/developing-applications/building-blocks/state-management/query-state-store/query-cosmosdb-store.md @@ -3,20 +3,33 @@ type: docs title: "Azure Cosmos DB" linkTitle: "Azure Cosmos DB" weight: 1000 -description: "Use Azure Cosmos DB as a backend state store" +description: "Use Azure Cosmos DB as a state store" --- -Dapr doesn't transform state values while saving and retrieving states. Dapr requires all state store implementations to abide by a certain key format scheme (see [Dapr state management spec]({{< ref state_api.md >}}). You can directly interact with the underlying store to manipulate the state data, such querying states, creating aggregated views and making backups. +Dapr doesn't transform state values while saving and retrieving states. Dapr requires all state store implementations to abide by a certain key format scheme (see [the state management spec]({{< ref state_api.md >}}). You can directly interact with the underlying store to manipulate the state data, such as: -> **NOTE:** Azure Cosmos DB is a multi-modal database that supports multiple APIs. The default Dapr Cosmos DB state store implementation uses the [Azure Cosmos DB SQL API](https://docs.microsoft.com/azure/cosmos-db/sql-query-getting-started). +- Querying states. +- Creating aggregated views. +- Making backups. -## 1. Connect to Azure Cosmos DB +{{% alert title="Note" color="primary" %}} +Azure Cosmos DB is a multi-modal database that supports multiple APIs. The default Dapr Cosmos DB state store implementation uses the [Azure Cosmos DB SQL API](https://docs.microsoft.com/azure/cosmos-db/sql-query-getting-started). -The easiest way to connect to your Cosmos DB instance is to use the Data Explorer on [Azure Management Portal](https://portal.azure.com). Alternatively, you can use [various SDKs and tools](https://docs.microsoft.com/azure/cosmos-db/mongodb-introduction). +{{% /alert %}} -> **NOTE:** The following samples use Cosmos DB [SQL API](https://docs.microsoft.com/azure/cosmos-db/sql-query-getting-started). When you configure an Azure Cosmos DB for Dapr, you need to specify the exact database and collection to use. The follow samples assume you've already connected to the right database and a collection named "states". +## Connect to Azure Cosmos DB -## 2. List keys by App ID +To connect to your Cosmos DB instance, you can either: + +- Use the Data Explorer on [Azure Management Portal](https://portal.azure.com). +- Use [various SDKs and tools](https://docs.microsoft.com/azure/cosmos-db/mongodb-introduction). + +{{% alert title="Note" color="primary" %}} +When you configure an Azure Cosmos DB for Dapr, specify the exact database and collection to use. The following Cosmos DB [SQL API](https://docs.microsoft.com/azure/cosmos-db/sql-query-getting-started) samples assume you've already connected to the right database and a collection named "states". + +{{% /alert %}} + +## List keys by App ID To get all state keys associated with application "myapp", use the query: @@ -24,9 +37,9 @@ To get all state keys associated with application "myapp", use the query: SELECT * FROM states WHERE CONTAINS(states.id, 'myapp||') ``` -The above query returns all documents with id containing "myapp-", which is the prefix of the state keys. +The above query returns all documents with an id containing "myapp-", which is the prefix of the state keys. -## 3. Get specific state data +## Get specific state data To get the state data by a key "balance" for the application "myapp", use the query: @@ -34,15 +47,13 @@ To get the state data by a key "balance" for the application "myapp", use the qu SELECT * FROM states WHERE states.id = 'myapp||balance' ``` -Then, read the **value** field of the returned document. - -To get the state version/ETag, use the command: +Read the **value** field of the returned document. To get the state version/ETag, use the command: ```sql SELECT states._etag FROM states WHERE states.id = 'myapp||balance' ``` -## 4. Read actor state +## Read actor state To get all the state keys associated with an actor with the instance ID "leroy" of actor type "cat" belonging to the application with ID "mypets", use the command: @@ -56,4 +67,7 @@ And to get a specific actor state such as "food", use the command: SELECT * FROM states WHERE states.id = 'mypets||cat||leroy||food' ``` -> **WARNING:** You should not manually update or delete states in the store. All writes and delete operations should be done via the Dapr runtime. +{{% alert title="Warning" color="warning" %}} +You should not manually update or delete states in the store. All writes and delete operations should be done via the Dapr runtime. **The only exception:** it is often required to delete actor records in a state store, _once you know that these are no longer in use_, to prevent a build up of unused actor instances that may never be loaded again. + +{{% /alert %}} diff --git a/daprdocs/content/en/developing-applications/building-blocks/state-management/query-state-store/query-redis-store.md b/daprdocs/content/en/developing-applications/building-blocks/state-management/query-state-store/query-redis-store.md index 42e4eee16..dea5e3c65 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/state-management/query-state-store/query-redis-store.md +++ b/daprdocs/content/en/developing-applications/building-blocks/state-management/query-state-store/query-redis-store.md @@ -3,22 +3,29 @@ type: docs title: "Redis" linkTitle: "Redis" weight: 2000 -description: "Use Redis as a backend state store" +description: "Use Redis as a state store" --- -Dapr doesn't transform state values while saving and retrieving states. Dapr requires all state store implementations to abide by a certain key format scheme (see [Dapr state management spec]({{}}). You can directly interact with the underlying store to manipulate the state data, such as querying states, creating aggregated views and making backups. +Dapr doesn't transform state values while saving and retrieving states. Dapr requires all state store implementations to abide by a certain key format scheme (see [the state management spec]({{< ref state_api.md >}}). You can directly interact with the underlying store to manipulate the state data, such as: ->**NOTE:** The following examples uses Redis CLI against a Redis store using the default Dapr state store implementation. +- Querying states. +- Creating aggregated views. +- Making backups. -## 1. Connect to Redis +{{% alert title="Note" color="primary" %}} +The following examples uses Redis CLI against a Redis store using the default Dapr state store implementation. -You can use the official [redis-cli](https://redis.io/topics/rediscli) or any other Redis compatible tools to connect to the Redis state store to directly query Dapr states. If you are running Redis in a container, the easiest way to use redis-cli is to use a container: +{{% /alert %}} + +## Connect to Redis + +You can use the official [redis-cli](https://redis.io/topics/rediscli) or any other Redis compatible tools to connect to the Redis state store to query Dapr states directly. If you are running Redis in a container, the easiest way to use redis-cli is via a container: ```bash docker run --rm -it --link redis redis-cli -h ``` -## 2. List keys by App ID +## List keys by App ID To get all state keys associated with application "myapp", use the command: @@ -33,9 +40,12 @@ The above command returns a list of existing keys, for example: 2) "myapp||amount" ``` -## 3. Get specific state data +## Get specific state data -Dapr saves state values as hash values. Each hash value contains a "data" field, which contains the state data and a "version" field, which contains an ever-incrementing version serving as the ETag. +Dapr saves state values as hash values. Each hash value contains a "data" field, which contains: + +- The state data. +- A "version" field, with an ever-incrementing version serving as the ETag. For example, to get the state data by a key "balance" for the application "myapp", use the command: @@ -49,7 +59,7 @@ To get the state version/ETag, use the command: HGET myapp||balance version ``` -## 4. Read actor state +## Read actor state To get all the state keys associated with an actor with the instance ID "leroy" of actor type "cat" belonging to the application with ID "mypets", use the command: @@ -57,10 +67,13 @@ To get all the state keys associated with an actor with the instance ID "leroy" KEYS mypets||cat||leroy* ``` -And to get a specific actor state such as "food", use the command: +To get a specific actor state such as "food", use the command: ```bash HGET mypets||cat||leroy||food value ``` -> **WARNING:** You should not manually update or delete states in the store. All writes and delete operations should be done via the Dapr runtime. +{{% alert title="Warning" color="warning" %}} +You should not manually update or delete states in the store. All writes and delete operations should be done via the Dapr runtime. **The only exception:** it is often required to delete actor records in a state store, _once you know that these are no longer in use_, to prevent a build up of unused actor instances that may never be loaded again. + +{{% /alert %}} \ No newline at end of file diff --git a/daprdocs/content/en/developing-applications/building-blocks/state-management/query-state-store/query-sqlserver-store.md b/daprdocs/content/en/developing-applications/building-blocks/state-management/query-state-store/query-sqlserver-store.md index 641724959..0034045a0 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/state-management/query-state-store/query-sqlserver-store.md +++ b/daprdocs/content/en/developing-applications/building-blocks/state-management/query-state-store/query-sqlserver-store.md @@ -6,15 +6,25 @@ weight: 3000 description: "Use SQL server as a backend state store" --- -Dapr doesn't transform state values while saving and retrieving states. Dapr requires all state store implementations to abide by a certain key format scheme (see [Dapr state management spec]({{< ref state_api.md >}}). You can directly interact with the underlying store to manipulate the state data, such querying states, creating aggregated views and making backups. +Dapr doesn't transform state values while saving and retrieving states. Dapr requires all state store implementations to abide by a certain key format scheme (see [the state management spec]({{< ref state_api.md >}}). You can directly interact with the underlying store to manipulate the state data, such as: -## 1. Connect to SQL Server +- Querying states. +- Creating aggregated views. +- Making backups. -The easiest way to connect to your SQL Server instance is to use the [Azure Data Studio](https://docs.microsoft.com/sql/azure-data-studio/download-azure-data-studio) (Windows, macOS, Linux) or [SQL Server Management Studio](https://docs.microsoft.com/sql/ssms/download-sql-server-management-studio-ssms) (Windows). +## Connect to SQL Server -> **NOTE:** The following samples use Azure SQL. When you configure an Azure SQL database for Dapr, you need to specify the exact table name to use. The follow samples assume you've already connected to the right database with a table named "states". +The easiest way to connect to your SQL Server instance is to use the: -## 2. List keys by App ID +- [Azure Data Studio](https://docs.microsoft.com/sql/azure-data-studio/download-azure-data-studio) (Windows, macOS, Linux) +- [SQL Server Management Studio](https://docs.microsoft.com/sql/ssms/download-sql-server-management-studio-ssms) (Windows) + +{{% alert title="Note" color="primary" %}} +When you configure an Azure SQL database for Dapr, you need to specify the exact table name to use. The following Azure SQL samples assume you've already connected to the right database with a table named "states". + +{{% /alert %}} + +## List keys by App ID To get all state keys associated with application "myapp", use the query: @@ -24,7 +34,7 @@ SELECT * FROM states WHERE [Key] LIKE 'myapp||%' The above query returns all rows with id containing "myapp||", which is the prefix of the state keys. -## 3. Get specific state data +## Get specific state data To get the state data by a key "balance" for the application "myapp", use the query: @@ -32,15 +42,13 @@ To get the state data by a key "balance" for the application "myapp", use the qu SELECT * FROM states WHERE [Key] = 'myapp||balance' ``` -Then, read the **Data** field of the returned row. - -To get the state version/ETag, use the command: +Read the **Data** field of the returned row. To get the state version/ETag, use the command: ```sql SELECT [RowVersion] FROM states WHERE [Key] = 'myapp||balance' ``` -## 4. Get filtered state data +## Get filtered state data To get all state data where the value "color" in json data equals to "blue", use the query: @@ -48,7 +56,7 @@ To get all state data where the value "color" in json data equals to "blue", use SELECT * FROM states WHERE JSON_VALUE([Data], '$.color') = 'blue' ``` -## 5. Read actor state +## Read actor state To get all the state keys associated with an actor with the instance ID "leroy" of actor type "cat" belonging to the application with ID "mypets", use the command: @@ -56,10 +64,13 @@ To get all the state keys associated with an actor with the instance ID "leroy" SELECT * FROM states WHERE [Key] LIKE 'mypets||cat||leroy||%' ``` -And to get a specific actor state such as "food", use the command: +To get a specific actor state such as "food", use the command: ```sql SELECT * FROM states WHERE [Key] = 'mypets||cat||leroy||food' ``` -> **WARNING:** You should not manually update or delete states in the store. All writes and delete operations should be done via the Dapr runtime. +{{% alert title="Warning" color="warning" %}} +You should not manually update or delete states in the store. All writes and delete operations should be done via the Dapr runtime. **The only exception:** it is often required to delete actor records in a state store, _once you know that these are no longer in use_, to prevent a build up of unused actor instances that may never be loaded again. + +{{% /alert %}} \ No newline at end of file diff --git a/daprdocs/content/en/developing-applications/building-blocks/state-management/state-management-overview.md b/daprdocs/content/en/developing-applications/building-blocks/state-management/state-management-overview.md index e7dd518f1..1e654f4c7 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/state-management/state-management-overview.md +++ b/daprdocs/content/en/developing-applications/building-blocks/state-management/state-management-overview.md @@ -6,65 +6,76 @@ weight: 100 description: "Overview of the state management API building block" --- -## Introduction +Your application can use Dapr's state management API to save, read, and query key/value pairs in the [supported state stores]({{< ref supported-state-stores.md >}}). Using a state store component, you can build stateful, long running applications that save and retrieve their state (like a shopping cart or a game's session state). For example, in the diagram below: -Using state management, your application can store and query data as key/value pairs in the [supported state stores]({{< ref supported-state-stores.md >}}). This enables you to build stateful, long running applications that can save and retrieve their state, for example a shopping cart or a game's session state. +- Use **HTTP POST** to save or query key/value pairs. +- Use **HTTP GET** to read a specific key and have its value returned. -When using state management, your application can leverage features that would otherwise be complicated and error-prone to build yourself such as: + + +## Features + +With state management, your application can leverage features that are typically complicated and error-prone to build, including: - Setting the choices on concurrency control and data consistency. - Performing bulk update operations [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) including multiple transactional operations. - Querying and filtering the key/value data. -Your application can use Dapr's state management API to save, read and query key/value pairs using a state store component, as shown in the diagram below. For example, by using HTTP POST you can save or query key/value pairs and by using HTTP GET you can read a specific key and have its value returned. - - - -## Features These are the features available as part of the state management API: ### Pluggable state stores + Dapr data stores are modeled as components, which can be swapped out without any changes to your service code. See [supported state stores]({{< ref supported-state-stores >}}) to see the list. ### Configurable state store behaviors -Dapr allows you to include additional metadata in a state operation request that describes how the request is expected to be handled. You can attach: + +With Dapr, you can include additional metadata in a state operation request that describes how you expect the request to be handled. You can attach: + - Concurrency requirements - Consistency requirements -By default, your application should assume a data store is **eventually consistent** and uses a **last-write-wins** concurrency pattern. +By default, your application should assume a data store is **eventually consistent** and uses a **last-write-wins concurrency pattern**. -[Not all stores are created equal]({{< ref supported-state-stores.md >}}). To ensure portability of your application you can query the metadata capabilities of the store and make your code adaptive to different store capabilities. +[Not all stores are created equal]({{< ref supported-state-stores.md >}}). To ensure your application's portability, you can query the metadata capabilities of the store and make your code adaptive to different store capabilities. -### Concurrency -Dapr supports Optimistic Concurrency Control (OCC) using ETags. When a state value is requested, Dapr always attaches an ETag property to the returned state. When the user code tries to update or delete a state, it’s expected to attach the ETag either through the request body for updates or the `If-Match` header for deletes. The write operation can succeed only when the provided ETag matches with the ETag in the state store. +#### Concurrency -Dapr chooses OCC because in many applications, data update conflicts are rare because clients are naturally partitioned by business contexts to operate on different data. However, if your application chooses to use ETags, a request may get rejected because of mismatched ETags. It's recommended that you use a retry policy in your code to compensate for such conflicts when using ETags. +Dapr supports Optimistic Concurrency Control (OCC) using ETags. When a state value is requested, Dapr always attaches an ETag property to the returned state. When the user code: -If your application omits ETags in writing requests, Dapr skips ETag checks while handling the requests. This essentially enables the **last-write-wins** pattern, compared to the **first-write-wins** pattern with ETags. +- **Updates a state**, it's expected to attach the ETag through the request body. +- **Deletes a state**, it’s expected to attach the ETag through the `If-Match` header. + +The `write` operation succeeds when the provided ETag matches the ETag in the state store. + +##### Why Dapr chooses optimistic concurrency control (OCC) + +Data update conflicts are rare in many applications, since clients are naturally partitioned by business contexts to operate on different data. However, if your application chooses to use ETags, mismatched ETags may cause a request rejection. It's recommended you use a retry policy in your code to compensate for conflicts when using ETags. + +If your application omits ETags in writing requests, Dapr skips ETag checks while handling the requests. This enables the **last-write-wins** pattern, compared to the **first-write-wins** pattern with ETags. {{% alert title="Note on ETags" color="primary" %}} -For stores that don't natively support ETags, it's expected that the corresponding Dapr state store implementation simulates ETags and follows the Dapr state management API specification when handling states. Because Dapr state store implementations are technically clients to the underlying data store, such simulation should be straightforward using the concurrency control mechanisms provided by the store. +For stores that don't natively support ETags, the corresponding Dapr state store implementation is expected to simulate ETags and follow the Dapr state management API specification when handling states. Since Dapr state store implementations are technically clients to the underlying data store, simulation should be straightforward, using the concurrency control mechanisms provided by the store. {{% /alert %}} Read the [API reference]({{< ref state_api.md >}}) to learn how to set concurrency options. -### Consistency +#### Consistency + Dapr supports both **strong consistency** and **eventual consistency**, with eventual consistency as the default behavior. -When strong consistency is used, Dapr waits for all replicas (or designated quorums) to acknowledge before it acknowledges a write request. When eventual consistency is used, Dapr returns as soon as the write request is accepted by the underlying data store, even if this is a single replica. +- **Strong consistency**: Dapr waits for all replicas (or designated quorums) to acknowledge before it acknowledges a write request. +- **Eventual consistency**: Dapr returns as soon as the write request is accepted by the underlying data store, even if this is a single replica. Read the [API reference]({{< ref state_api.md >}}) to learn how to set consistency options. ### Setting content type -Some state store components might have different ways of maintaining and manipulating data, depending on its type. -Dapr supports passing content type in [State management API](#state-management-api) as part of request metadata. +State store components may maintain and manipulate data differently, depending on the content type. Dapr supports passing content type in [state management API](#state-management-api) as part of request metadata. -Setting the content type is optional, and it is up to the component to make use of it. Dapr only provides the means of passing this information to the component. +Setting the content type is _optional_, and the component decides whether to make use of it. Dapr only provides the means of passing this information to the component. -With the HTTP API, you can set content type via URL query parameter `metadata.contentType`. For example, `http://localhost:3500/v1.0/state/store?metadata.contentType=application/json` - -With the gRPC API, you can set content type by adding key/value pair `"contentType" : ` to the request metadata. +- **With the HTTP API**: Set content type via URL query parameter `metadata.contentType`. For example, `http://localhost:3500/v1.0/state/store?metadata.contentType=application/json`. +- **With the gRPC API**: Set content type by adding key/value pair `"contentType" : ` to the request metadata. ### Multiple operations @@ -76,26 +87,41 @@ You can group multiple read requests into a bulk (or batch) operation. In the bu #### Transactional operations -You can group write, update and delete operations into a request, which are then handled as an atomic transaction. The request will succeed or fail as a transactional set of operations. +You can group write, update, and delete operations into a request, which are then handled as an atomic transaction. The request will succeed or fail as a transactional set of operations. + +### Actor state + +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. ### State encryption + Dapr supports automatic client encryption of application state with support for key rotations. This is supported on all Dapr state stores. For more info, read the [How-To: Encrypt application state]({{< ref howto-encrypt-state.md >}}) topic. ### Shared state between applications -Different applications might have different needs when it comes to sharing state. For example, in one scenario you may want to encapsulate all state within a given application and have Dapr manage the access for you. In a different scenario, you may need to have two applications working on the same state be able to get and save the same keys. Dapr enable states to be isolated to an application, shared in a state store between applications or have multiple applications share state across different state stores. For more details read [How-To: Share state between applications]({{< ref howto-share-state.md >}}), -### Actor state -Transactional state stores can be used to store actor state. To specify which state store to be used for actors, specify value of property `actorStateStore` as `true` in the metadata section of the state store component. Actors state is stored with a specific scheme in transactional state stores, which allows for consistent querying. Only a single state store component can be used as the state store for all actors. Read the [API reference]({{< ref state_api.md >}}) to learn more about state stores for actors and the [actors API reference]({{< ref actors_api.md >}}) +Different applications' needs vary when it comes to sharing state. In one scenario, you may want to encapsulate all state within a given application and have Dapr manage the access for you. In another scenario, you may want two applications working on the same state to get and save the same keys. + +Dapr enables states to be: + +- Isolated to an application. +- Shared in a state store between applications. +- Shared between multiple applications across different state stores. + +For more details read [How-To: Share state between applications]({{< ref howto-share-state.md >}}), + +### Querying state -### Querying state There are two ways to query the state: - * Using the state management query API provided in Dapr runtime. - * Querying state store directly with the store's native SDK. + +- Using the state management query API provided in Dapr runtime. +- Querying state store directly with the store's native SDK. #### Query API -The [query API]({{< ref "reference/api/state_api.md#query-state" >}}) provides a way of querying the key/value data saved using state management in state stores regardless of underlying database or storage technology. It is an optional state management API. Using the state management query API you can filter, sort and paginate the key/value data. For more details read [How-To: Query state]({{< ref howto-state-query-api.md >}}). + +Using the _optional_ state management [query API]({{< ref "reference/api/state_api.md#query-state" >}}), you can query the key/value data saved in state stores, regardless of underlying database or storage technology. With the state management query API, you can filter, sort, and paginate the key/value data. For more details read [How-To: Query state]({{< ref howto-state-query-api.md >}}). #### Querying state store directly + Dapr saves and retrieves state values without any transformation. You can query and aggregate state directly from the [underlying state store]({{< ref query-state-store >}}). For example, to get all state keys associated with an application ID "myApp" in Redis, use: @@ -104,37 +130,52 @@ KEYS "myApp*" ``` {{% alert title="Note on direct queries" color="primary" %}} -Direct queries of the state store are not governed by Dapr concurrency control, since you are not calling through the Dapr runtime. What you see are snapshots of committed data which are acceptable for read-only queries across multiple actors, however writes should be done via the Dapr state management or actors APIs. +Since you aren't calling through the Dapr runtime, direct queries of the state store are not governed by Dapr concurrency control. What you see are snapshots of committed data acceptable for read-only queries across multiple actors. Writes should be done via the Dapr state management or actors APIs. {{% /alert %}} ##### Querying actor state -If the data store supports SQL queries, you can query an actor's state using SQL queries. For example use: + +If the data store supports SQL queries, you can query an actor's state using SQL queries. For example: ```sql SELECT * FROM StateTable WHERE Id='||||||' ``` -You can also perform aggregate queries across actor instances, avoiding the common turn-based concurrency limitations of actor frameworks. For example, to calculate the average temperature of all thermometer actors, use: +You can also avoid the common turn-based concurrency limitations of actor frameworks by performing aggregate queries across actor instances. For example, to calculate the average temperature of all thermometer actors, use: ```sql SELECT AVG(value) FROM StateTable WHERE Id LIKE '||||*||temperature' ``` ### State Time-to-Live (TTL) -Dapr enables per state set request time-to-live (TTL). This means that applications can set time-to-live per state stored, and these states cannot be retrieved after expiration. + +Dapr enables [per state set request time-to-live (TTL)]({{< ref state-store-ttl.md >}}). This means that applications can set time-to-live per state stored, and these states cannot be retrieved after expiration. ### State management API -The state management API can be found in the [state management API reference]({{< ref state_api.md >}}) which describes how to retrieve, save, delete and query state values by providing keys. + +The state management API can be found in the [state management API reference]({{< ref state_api.md >}}), which describes how to retrieve, save, delete, and query state values by providing keys. + +## Try out state management + +### Quickstarts and tutorials + +Want to put the Dapr state management API to the test? Walk through the following quickstart and tutorials to see state management in action: + +| Quickstart/tutorial | Description | +| ------------------- | ----------- | +| [State management quickstart]({{< ref statemanagement-quickstart.md >}}) | Create stateful applications using the state management API. | +| [Hello World](https://github.com/dapr/quickstarts/tree/master/tutorials/hello-world) | _Recommended_
Demonstrates how to run Dapr locally. Highlights service invocation and state management. | +| [Hello World Kubernetes](https://github.com/dapr/quickstarts/tree/master/tutorials/hello-kubernetes) | _Recommended_
Demonstrates how to run Dapr in Kubernetes. Highlights service invocation and _state management_. | + +### Start using state management directly in your app + +Want to skip the quickstarts? Not a problem. You can try out the state management building block directly in your application. After [Dapr is installed]({{< ref "getting-started/_index.md" >}}), you can begin using the state management API starting with [the state management how-to guide]({{< ref howto-get-save-state.md >}}). ## Next steps -* Follow these guides on: - * [How-To: Save and get state]({{< ref howto-get-save-state.md >}}) - * [How-To: Build a stateful service]({{< ref howto-stateful-service.md >}}) - * [How-To: Share state between applications]({{< ref howto-share-state.md >}}) - * [How-To: Query state]({{< ref howto-state-query-api.md >}}) - * [How-To: Encrypt application state]({{< ref howto-encrypt-state.md >}}) - * [State Time-to-Live]({{< ref state-store-ttl.md >}}) -* Try out the [hello world quickstart](https://github.com/dapr/quickstarts/blob/master/tutorials/hello-world/README.md) which shows how to use state management or try the samples in the [Dapr SDKs]({{< ref sdks >}}) -* List of [state store components]({{< ref supported-state-stores.md >}}) -* Read the [state management API reference]({{< ref state_api.md >}}) -* Read the [actors API reference]({{< ref actors_api.md >}}) + +- Start working through the state management how-to guides, starting with: + - [How-To: Save and get state]({{< ref howto-get-save-state.md >}}) + - [How-To: Build a stateful service]({{< ref howto-stateful-service.md >}}) +- Review the list of [state store components]({{< ref supported-state-stores.md >}}) +- Read the [state management API reference]({{< ref state_api.md >}}) +- Read the [actors API reference]({{< ref actors_api.md >}}) \ No newline at end of file diff --git a/daprdocs/content/en/developing-applications/building-blocks/state-management/state-store-ttl.md b/daprdocs/content/en/developing-applications/building-blocks/state-management/state-store-ttl.md index f40c723ae..1b3538f9a 100644 --- a/daprdocs/content/en/developing-applications/building-blocks/state-management/state-store-ttl.md +++ b/daprdocs/content/en/developing-applications/building-blocks/state-management/state-store-ttl.md @@ -6,18 +6,15 @@ weight: 500 description: "Manage state with TTL." --- -## Introduction - Dapr enables per state set request time-to-live (TTL). This means that applications can set time-to-live per state stored, and these states cannot be retrieved after expiration. -Only a subset of Dapr [state store components]({{< ref supported-state-stores >}}) are compatible with state TTL. For supported state stores simply set the `ttlInSeconds` metadata when publishing a message. Other state stores will ignore this value. - -Some state stores can specify a default expiration on a per-table/container basis. Please refer to the official documentation of these state stores to utilize this feature of desired. Dapr support per-state TTLs for supported state stores. +For [supported state stores]({{< ref supported-state-stores >}}), you simply set the `ttlInSeconds` metadata when publishing a message. Other state stores will ignore this value. For some state stores, you can specify a default expiration on a per-table/container basis. ## Native state TTL support -When state time-to-live has native support in the state store component, Dapr simply forwards the time-to-live configuration without adding any extra logic, keeping predictable behavior. This is helpful when the expired state is handled differently by the component. -When a TTL is not specified the default behavior of the state store is retained. +When state TTL has native support in the state store component, Dapr forwards the TTL configuration without adding any extra logic, maintaining predictable behavior. This is helpful when the expired state is handled differently by the component. + +When a TTL is not specified, the default behavior of the state store is retained. ## Persisting state (ignoring an existing TTL) @@ -25,11 +22,11 @@ To explicitly persist a state (ignoring any TTLs set for the key), specify a `tt ## Supported components -Please refer to the TTL column in the tables at [state store components]({{< ref supported-state-stores >}}). +Refer to the TTL column in the [state store components guide]({{< ref supported-state-stores >}}). ## Example -State TTL can be set in the metadata as part of the state store set request: +You can set state TTL in the metadata as part of the state store set request: {{< tabs Python "HTTP API (Bash)" "HTTP API (PowerShell)">}} @@ -51,7 +48,7 @@ with DaprClient() as client: ``` -Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application: +To launch a Dapr sidecar and run the above example application, you'd then run a command similar to the following: ```bash dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 -- python3 OrderProcessingService.py @@ -77,10 +74,9 @@ Invoke-RestMethod -Method Post -ContentType 'application/json' -Body '[{"key": " {{< /tabs >}} -See [this guide]({{< ref state_api.md >}}) for a reference on the state API. - ## Related links -- Learn [how to use key value pairs to persist a state]({{< ref howto-get-save-state.md >}}) -- List of [state store components]({{< ref supported-state-stores >}}) -- Read the [API reference]({{< ref state_api.md >}}) +- See [the state API reference guide]({{< ref state_api.md >}}). +- Learn [how to use key value pairs to persist a state]({{< ref howto-get-save-state.md >}}). +- List of [state store components]({{< ref supported-state-stores >}}). +- Read the [API reference]({{< ref state_api.md >}}). From 58ae69de5416240095e9368bbc6c699c7cac4c6f Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 6 Jul 2022 17:19:26 -0500 Subject: [PATCH 42/42] Adds settings for SASL SCRAM SHA-256 and SHA-512 (#2621) * Adds settings for SASL SCRAM SHA-256 and SHA-512 Signed-off-by: Andrew * Update setup-apache-kafka.md Signed-off-by: Andrew --- .../supported-pubsub/setup-apache-kafka.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-apache-kafka.md b/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-apache-kafka.md index 034c87279..2941dc64f 100644 --- a/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-apache-kafka.md +++ b/daprdocs/content/en/reference/components-reference/supported-pubsub/setup-apache-kafka.md @@ -35,6 +35,8 @@ spec: secretKeyRef: name: kafka-secrets key: saslPasswordSecret + - name: saslMechanism + value: "SHA-512" - name: maxMessageBytes # Optional. value: 1024 - name: consumeRetryInterval # Optional. @@ -56,6 +58,7 @@ spec: | authType | Y | Configure or disable authentication. Supported values: `none`, `password`, `mtls`, or `oidc` | `"password"`, `"none"` | saslUsername | N | The SASL username used for authentication. Only required if `authType` is set to `"password"`. | `"adminuser"` | saslPassword | N | The SASL password used for authentication. Can be `secretKeyRef` to use a [secret reference]({{< ref component-secrets.md >}}). Only required if `authType is set to `"password"`. | `""`, `"KeFg23!"` +| saslMechanism | N | The SASL Authentication Mechanism you wish to use. Only required if `authType` is set to `"password"`. Defaults to `PLAINTEXT` | `"SHA-512", "SHA-256", "PLAINTEXT"` | initialOffset | N | The initial offset to use if no offset was previously committed. Should be "newest" or "oldest". Defaults to "newest". | `"oldest"` | maxMessageBytes | N | The maximum size in bytes allowed for a single Kafka message. Defaults to 1024. | `2048` | consumeRetryInterval | N | The interval between retries when attempting to consume topics. Treats numbers without suffix as milliseconds. Defaults to 100ms. | `200ms` | @@ -113,8 +116,7 @@ spec: #### SASL Password -Setting `authType` to `password` enables [SASL](https://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer) authentication using the **PLAIN** mechanism. This requires setting -the `saslUsername` and `saslPassword` fields. +Setting `authType` to `password` enables [SASL](https://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer) authentication. This requires setting the `saslUsername` and `saslPassword` fields. ```yaml apiVersion: dapr.io/v1alpha1 @@ -140,6 +142,8 @@ spec: secretKeyRef: name: kafka-secrets key: saslPasswordSecret + - name: saslMechanism + value: "SHA-512" - name: maxMessageBytes # Optional. value: 1024 - name: consumeRetryInterval # Optional.