How-To: Save and get state

Use key value pairs to persist a state

Introduction

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.

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.

Pre-requisites

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.

Diagram showing state management of example service

Step 1: Setup 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, but any state store from the supported list will work.

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.

To deploy this into a Kubernetes cluster, fill in the metadata connection details of your desired statestore component in the yaml below, save as statestore.yaml, and run kubectl apply -f statestore.yaml.

  1. apiVersion: dapr.io/v1alpha1
  2. kind: Component
  3. metadata:
  4. name: statestore
  5. namespace: default
  6. spec:
  7. type: state.redis
  8. version: v1
  9. metadata:
  10. - name: redisHost
  11. value: localhost:6379
  12. - name: redisPassword
  13. value: ""

See the instructions here on how to setup different state stores on Kubernetes.

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.

Note

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.

Below are code examples that leverage Dapr SDKs for saving and retrieving a single state.

  1. //dependencies
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Net.Http;
  5. using System.Net.Http.Headers;
  6. using System.Threading.Tasks;
  7. using Dapr.Client;
  8. using Microsoft.AspNetCore.Mvc;
  9. using System.Threading;
  10. using System.Text.Json;
  11. //code
  12. namespace EventService
  13. {
  14. class Program
  15. {
  16. static async Task Main(string[] args)
  17. {
  18. string DAPR_STORE_NAME = "statestore";
  19. while(true) {
  20. System.Threading.Thread.Sleep(5000);
  21. using var client = new DaprClientBuilder().Build();
  22. Random random = new Random();
  23. int orderId = random.Next(1,1000);
  24. //Using Dapr SDK to save and get state
  25. await client.SaveStateAsync(DAPR_STORE_NAME, "order_1", orderId.ToString());
  26. await client.SaveStateAsync(DAPR_STORE_NAME, "order_2", orderId.ToString());
  27. var result = await client.GetStateAsync<string>(DAPR_STORE_NAME, "order_1");
  28. Console.WriteLine("Result after get: " + result);
  29. }
  30. }
  31. }
  32. }

Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:

  1. dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 dotnet run
  1. //dependencies
  2. import io.dapr.client.DaprClient;
  3. import io.dapr.client.DaprClientBuilder;
  4. import io.dapr.client.domain.State;
  5. import io.dapr.client.domain.TransactionalStateOperation;
  6. import org.springframework.boot.autoconfigure.SpringBootApplication;
  7. import org.slf4j.Logger;
  8. import org.slf4j.LoggerFactory;
  9. import reactor.core.publisher.Mono;
  10. import java.util.Random;
  11. import java.util.concurrent.TimeUnit;
  12. //code
  13. @SpringBootApplication
  14. public class OrderProcessingServiceApplication {
  15. private static final Logger log = LoggerFactory.getLogger(OrderProcessingServiceApplication.class);
  16. private static final String STATE_STORE_NAME = "statestore";
  17. public static void main(String[] args) throws InterruptedException{
  18. while(true) {
  19. TimeUnit.MILLISECONDS.sleep(5000);
  20. Random random = new Random();
  21. int orderId = random.nextInt(1000-1) + 1;
  22. DaprClient client = new DaprClientBuilder().build();
  23. //Using Dapr SDK to save and get state
  24. client.saveState(STATE_STORE_NAME, "order_1", Integer.toString(orderId)).block();
  25. client.saveState(STATE_STORE_NAME, "order_2", Integer.toString(orderId)).block();
  26. Mono<State<String>> result = client.getState(STATE_STORE_NAME, "order_1", String.class);
  27. log.info("Result after get" + result);
  28. }
  29. }
  30. }

Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:

  1. dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 mvn spring-boot:run
  1. #dependencies
  2. import random
  3. from time import sleep
  4. import requests
  5. import logging
  6. from dapr.clients import DaprClient
  7. from dapr.clients.grpc._state import StateItem
  8. from dapr.clients.grpc._request import TransactionalStateOperation, TransactionOperationType
  9. #code
  10. logging.basicConfig(level = logging.INFO)
  11. DAPR_STORE_NAME = "statestore"
  12. while True:
  13. sleep(random.randrange(50, 5000) / 1000)
  14. orderId = random.randint(1, 1000)
  15. with DaprClient() as client:
  16. #Using Dapr SDK to save and get state
  17. client.save_state(DAPR_STORE_NAME, "order_1", str(orderId))
  18. result = client.get_state(DAPR_STORE_NAME, "order_1")
  19. 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:

  1. dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 -- python3 OrderProcessingService.py
  1. //dependencies
  2. import (
  3. "context"
  4. "log"
  5. "math/rand"
  6. "time"
  7. "strconv"
  8. dapr "github.com/dapr/go-sdk/client"
  9. )
  10. //code
  11. func main() {
  12. for i := 0; i < 10; i++ {
  13. time.Sleep(5000)
  14. orderId := rand.Intn(1000-1) + 1
  15. client, err := dapr.NewClient()
  16. STATE_STORE_NAME := "statestore"
  17. if err != nil {
  18. panic(err)
  19. }
  20. defer client.Close()
  21. ctx := context.Background()
  22. //Using Dapr SDK to save and get state
  23. if err := client.SaveState(ctx, STATE_STORE_NAME, "order_1", []byte(strconv.Itoa(orderId))); err != nil {
  24. panic(err)
  25. }
  26. result, err := client.GetState(ctx, STATE_STORE_NAME, "order_2")
  27. if err != nil {
  28. panic(err)
  29. }
  30. log.Println("Result after get: ")
  31. log.Println(result)
  32. }
  33. }

Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:

  1. dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 go run OrderProcessingService.go
  1. //dependencies
  2. import { DaprClient, HttpMethod, CommunicationProtocolEnum } from 'dapr-client';
  3. //code
  4. const daprHost = "127.0.0.1";
  5. var main = function() {
  6. for(var i=0;i<10;i++) {
  7. sleep(5000);
  8. var orderId = Math.floor(Math.random() * (1000 - 1) + 1);
  9. start(orderId).catch((e) => {
  10. console.error(e);
  11. process.exit(1);
  12. });
  13. }
  14. }
  15. async function start(orderId) {
  16. const client = new DaprClient(daprHost, process.env.DAPR_HTTP_PORT, CommunicationProtocolEnum.HTTP);
  17. const STATE_STORE_NAME = "statestore";
  18. //Using Dapr SDK to save and get state
  19. await client.state.save(STATE_STORE_NAME, [
  20. {
  21. key: "order_1",
  22. value: orderId.toString()
  23. },
  24. {
  25. key: "order_2",
  26. value: orderId.toString()
  27. }
  28. ]);
  29. var result = await client.state.get(STATE_STORE_NAME, "order_1");
  30. console.log("Result after get: " + result);
  31. }
  32. function sleep(ms) {
  33. return new Promise(resolve => setTimeout(resolve, ms));
  34. }
  35. main();

Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:

  1. dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 npm start

Begin by launching a Dapr sidecar:

  1. dapr run --app-id orderprocessing --dapr-http-port 3601

Then in a separate terminal save a key/value pair into your statestore:

  1. 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:

  1. 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.

Begin by launching a Dapr sidecar:

  1. dapr --app-id orderprocessing --port 3601 run

Then in a separate terminal save a key/value pair into your statestore:

  1. 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:

  1. Invoke-RestMethod -Uri '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.

Step 3: Delete state

Below are code examples that leverage Dapr SDKs for deleting the state.

  1. //dependencies
  2. using Dapr.Client;
  3. //code
  4. namespace EventService
  5. {
  6. class Program
  7. {
  8. static async Task Main(string[] args)
  9. {
  10. string DAPR_STORE_NAME = "statestore";
  11. //Using Dapr SDK to delete the state
  12. using var client = new DaprClientBuilder().Build();
  13. await client.DeleteStateAsync(DAPR_STORE_NAME, "order_1", cancellationToken: cancellationToken);
  14. }
  15. }
  16. }

Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:

  1. dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 dotnet run
  1. //dependencies
  2. import io.dapr.client.DaprClient;
  3. import io.dapr.client.DaprClientBuilder;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5. //code
  6. @SpringBootApplication
  7. public class OrderProcessingServiceApplication {
  8. public static void main(String[] args) throws InterruptedException{
  9. String STATE_STORE_NAME = "statestore";
  10. //Using Dapr SDK to delete the state
  11. DaprClient client = new DaprClientBuilder().build();
  12. String storedEtag = client.getState(STATE_STORE_NAME, "order_1", String.class).block().getEtag();
  13. client.deleteState(STATE_STORE_NAME, "order_1", storedEtag, null).block();
  14. }
  15. }

Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:

  1. dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 mvn spring-boot:run
  1. #dependencies
  2. from dapr.clients.grpc._request import TransactionalStateOperation, TransactionOperationType
  3. #code
  4. logging.basicConfig(level = logging.INFO)
  5. DAPR_STORE_NAME = "statestore"
  6. #Using Dapr SDK to delete the state
  7. with DaprClient() as client:
  8. 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:

  1. dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 -- python3 OrderProcessingService.py
  1. //dependencies
  2. import (
  3. "context"
  4. dapr "github.com/dapr/go-sdk/client"
  5. )
  6. //code
  7. func main() {
  8. STATE_STORE_NAME := "statestore"
  9. //Using Dapr SDK to delete the state
  10. client, err := dapr.NewClient()
  11. if err != nil {
  12. panic(err)
  13. }
  14. defer client.Close()
  15. ctx := context.Background()
  16. if err := client.DeleteState(ctx, STATE_STORE_NAME, "order_1"); err != nil {
  17. panic(err)
  18. }
  19. }

Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:

  1. dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 go run OrderProcessingService.go
  1. //dependencies
  2. import { DaprClient, HttpMethod, CommunicationProtocolEnum } from 'dapr-client';
  3. //code
  4. const daprHost = "127.0.0.1";
  5. var main = function() {
  6. const STATE_STORE_NAME = "statestore";
  7. //Using Dapr SDK to save and get state
  8. const client = new DaprClient(daprHost, process.env.DAPR_HTTP_PORT, CommunicationProtocolEnum.HTTP);
  9. await client.state.delete(STATE_STORE_NAME, "order_1");
  10. }
  11. main();

Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:

  1. dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 npm start

With the same Dapr instance running from above run:

  1. curl -X DELETE 'http://localhost:3601/v1.0/state/statestore/order_1'

Try getting state again and note that no value is returned.

With the same Dapr instance running from above run:

  1. 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.

Step 4: Save and retrieve multiple states

Below are code examples that leverage Dapr SDKs for saving and retrieving multiple states.

  1. //dependencies
  2. import io.dapr.client.DaprClient;
  3. import io.dapr.client.DaprClientBuilder;
  4. import io.dapr.client.domain.State;
  5. import java.util.Arrays;
  6. //code
  7. @SpringBootApplication
  8. public class OrderProcessingServiceApplication {
  9. private static final Logger log = LoggerFactory.getLogger(OrderProcessingServiceApplication.class);
  10. public static void main(String[] args) throws InterruptedException{
  11. String STATE_STORE_NAME = "statestore";
  12. //Using Dapr SDK to retrieve multiple states
  13. DaprClient client = new DaprClientBuilder().build();
  14. Mono<List<State<String>>> resultBulk = client.getBulkState(STATE_STORE_NAME,
  15. Arrays.asList("order_1", "order_2"), String.class);
  16. }
  17. }

Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:

  1. dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 mvn spring-boot:run
  1. #dependencies
  2. from dapr.clients import DaprClient
  3. from dapr.clients.grpc._state import StateItem
  4. #code
  5. logging.basicConfig(level = logging.INFO)
  6. DAPR_STORE_NAME = "statestore"
  7. orderId = 100
  8. #Using Dapr SDK to save and retrieve multiple states
  9. with DaprClient() as client:
  10. client.save_bulk_state(store_name=DAPR_STORE_NAME, states=[StateItem(key="order_2", value=str(orderId))])
  11. result = client.get_bulk_state(store_name=DAPR_STORE_NAME, keys=["order_1", "order_2"], states_metadata={"metakey": "metavalue"}).items
  12. 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:

  1. dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 -- python3 OrderProcessingService.py
  1. //dependencies
  2. import { DaprClient, HttpMethod, CommunicationProtocolEnum } from 'dapr-client';
  3. //code
  4. const daprHost = "127.0.0.1";
  5. var main = function() {
  6. const STATE_STORE_NAME = "statestore";
  7. var orderId = 100;
  8. //Using Dapr SDK to save and retrieve multiple states
  9. const client = new DaprClient(daprHost, process.env.DAPR_HTTP_PORT, CommunicationProtocolEnum.HTTP);
  10. await client.state.save(STATE_STORE_NAME, [
  11. {
  12. key: "order_1",
  13. value: orderId.toString()
  14. },
  15. {
  16. key: "order_2",
  17. value: orderId.toString()
  18. }
  19. ]);
  20. result = await client.state.getBulk(STATE_STORE_NAME, ["order_1", "order_2"]);
  21. }
  22. main();

Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:

  1. dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 npm start

With the same Dapr instance running from above save two key/value pairs into your statestore:

  1. 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:

  1. curl -X POST -H "Content-Type: application/json" -d '{"keys":["order_1", "order_2"]}' http://localhost:3601/v1.0/state/statestore/bulk

With the same Dapr instance running from above save two key/value pairs into your statestore:

  1. 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:

  1. Invoke-RestMethod -Method Post -ContentType 'application/json' -Body '{"keys":["order_1", "order_2"]}' -Uri 'http://localhost:3601/v1.0/state/statestore/bulk'

Step 5: Perform state transactions

Note

State transactions require a state store that supports multi-item transactions. Visit the supported state stores page page for a full list. Note that the default Redis container created in a self-hosted environment supports them.

Below are code examples that leverage Dapr SDKs for performing state transactions.

  1. //dependencies
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Net.Http;
  5. using System.Net.Http.Headers;
  6. using System.Threading.Tasks;
  7. using Dapr.Client;
  8. using Microsoft.AspNetCore.Mvc;
  9. using System.Threading;
  10. using System.Text.Json;
  11. //code
  12. namespace EventService
  13. {
  14. class Program
  15. {
  16. static async Task Main(string[] args)
  17. {
  18. string DAPR_STORE_NAME = "statestore";
  19. while(true) {
  20. System.Threading.Thread.Sleep(5000);
  21. Random random = new Random();
  22. int orderId = random.Next(1,1000);
  23. using var client = new DaprClientBuilder().Build();
  24. var requests = new List<StateTransactionRequest>()
  25. {
  26. new StateTransactionRequest("order_3", JsonSerializer.SerializeToUtf8Bytes(orderId.ToString()), StateOperationType.Upsert),
  27. new StateTransactionRequest("order_2", null, StateOperationType.Delete)
  28. };
  29. CancellationTokenSource source = new CancellationTokenSource();
  30. CancellationToken cancellationToken = source.Token;
  31. //Using Dapr SDK to perform the state transactions
  32. await client.ExecuteStateTransactionAsync(DAPR_STORE_NAME, requests, cancellationToken: cancellationToken);
  33. Console.WriteLine("Order requested: " + orderId);
  34. Console.WriteLine("Result: " + result);
  35. }
  36. }
  37. }
  38. }

Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:

  1. dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 dotnet run
  1. //dependencies
  2. import io.dapr.client.DaprClient;
  3. import io.dapr.client.DaprClientBuilder;
  4. import io.dapr.client.domain.State;
  5. import io.dapr.client.domain.TransactionalStateOperation;
  6. import org.springframework.boot.autoconfigure.SpringBootApplication;
  7. import org.slf4j.Logger;
  8. import org.slf4j.LoggerFactory;
  9. import reactor.core.publisher.Mono;
  10. import java.util.ArrayList;
  11. import java.util.List;
  12. import java.util.Random;
  13. import java.util.concurrent.TimeUnit;
  14. //code
  15. @SpringBootApplication
  16. public class OrderProcessingServiceApplication {
  17. private static final Logger log = LoggerFactory.getLogger(OrderProcessingServiceApplication.class);
  18. private static final String STATE_STORE_NAME = "statestore";
  19. public static void main(String[] args) throws InterruptedException{
  20. while(true) {
  21. TimeUnit.MILLISECONDS.sleep(5000);
  22. Random random = new Random();
  23. int orderId = random.nextInt(1000-1) + 1;
  24. DaprClient client = new DaprClientBuilder().build();
  25. List<TransactionalStateOperation<?>> operationList = new ArrayList<>();
  26. operationList.add(new TransactionalStateOperation<>(TransactionalStateOperation.OperationType.UPSERT,
  27. new State<>("order_3", Integer.toString(orderId), "")));
  28. operationList.add(new TransactionalStateOperation<>(TransactionalStateOperation.OperationType.DELETE,
  29. new State<>("order_2")));
  30. //Using Dapr SDK to perform the state transactions
  31. client.executeStateTransaction(STATE_STORE_NAME, operationList).block();
  32. log.info("Order requested: " + orderId);
  33. }
  34. }
  35. }

Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:

  1. dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 mvn spring-boot:run
  1. #dependencies
  2. import random
  3. from time import sleep
  4. import requests
  5. import logging
  6. from dapr.clients import DaprClient
  7. from dapr.clients.grpc._state import StateItem
  8. from dapr.clients.grpc._request import TransactionalStateOperation, TransactionOperationType
  9. #code
  10. logging.basicConfig(level = logging.INFO)
  11. DAPR_STORE_NAME = "statestore"
  12. while True:
  13. sleep(random.randrange(50, 5000) / 1000)
  14. orderId = random.randint(1, 1000)
  15. with DaprClient() as client:
  16. #Using Dapr SDK to perform the state transactions
  17. client.execute_state_transaction(store_name=DAPR_STORE_NAME, operations=[
  18. TransactionalStateOperation(
  19. operation_type=TransactionOperationType.upsert,
  20. key="order_3",
  21. data=str(orderId)),
  22. TransactionalStateOperation(key="order_3", data=str(orderId)),
  23. TransactionalStateOperation(
  24. operation_type=TransactionOperationType.delete,
  25. key="order_2",
  26. data=str(orderId)),
  27. TransactionalStateOperation(key="order_2", data=str(orderId))
  28. ])
  29. client.delete_state(store_name=DAPR_STORE_NAME, key="order_1")
  30. logging.basicConfig(level = logging.INFO)
  31. logging.info('Order requested: ' + str(orderId))
  32. 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:

  1. dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 -- python3 OrderProcessingService.py
  1. //dependencies
  2. import { DaprClient, HttpMethod, CommunicationProtocolEnum } from 'dapr-client';
  3. //code
  4. const daprHost = "127.0.0.1";
  5. var main = function() {
  6. for(var i=0;i<10;i++) {
  7. sleep(5000);
  8. var orderId = Math.floor(Math.random() * (1000 - 1) + 1);
  9. start(orderId).catch((e) => {
  10. console.error(e);
  11. process.exit(1);
  12. });
  13. }
  14. }
  15. async function start(orderId) {
  16. const client = new DaprClient(daprHost, process.env.DAPR_HTTP_PORT, CommunicationProtocolEnum.HTTP);
  17. const STATE_STORE_NAME = "statestore";
  18. //Using Dapr SDK to save and retrieve multiple states
  19. await client.state.transaction(STATE_STORE_NAME, [
  20. {
  21. operation: "upsert",
  22. request: {
  23. key: "order_3",
  24. value: orderId.toString()
  25. }
  26. },
  27. {
  28. operation: "delete",
  29. request: {
  30. key: "order_2"
  31. }
  32. }
  33. ]);
  34. }
  35. function sleep(ms) {
  36. return new Promise(resolve => setTimeout(resolve, ms));
  37. }
  38. main();

Navigate to the directory containing the above code, then run the following command to launch a Dapr sidecar and run the application:

  1. dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 npm start

With the same Dapr instance running from above perform two state transactions:

  1. 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:

  1. curl -X POST -H "Content-Type: application/json" -d '{"keys":["order_1", "order_2"]}' http://localhost:3601/v1.0/state/statestore/bulk

With the same Dapr instance running from above save two key/value pairs into your statestore:

  1. 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:

  1. Invoke-RestMethod -Method Post -ContentType 'application/json' -Body '{"keys":["order_1", "order_2"]}' -Uri 'http://localhost:3601/v1.0/state/statestore/bulk'

Next steps

Last modified February 18, 2022: Update setup-jetstream.md (#2200) (428d8c2)