Quickstart: State Management

Get started with Dapr’s State Management building block

Let’s take a look at Dapr’s State Management building block. In this Quickstart, you will save, get, and delete state using a Redis state store, but you can swap this out for any one of the supported state stores.

Select your preferred language-specific Dapr SDK before proceeding with the Quickstart.


Pre-requisites

For this example, you will need:

Step 1: Set up the environment

Clone the sample provided in the Quickstarts repo.

git clone https://github.com/dapr/quickstarts.git

Step 2: Manipulate service state

In a terminal window, navigate to the order-processor directory.

cd state_management/python/sdk/order-processor

Install the dependencies:

pip3 install -r requirements.txt

Run the order-processor service alongside a Dapr sidecar.

dapr run --app-id order-processor --components-path ../../../components/ -- python3 app.py

Note: Since Python3.exe is not defined in Windows, you may need to use python app.py instead of python3 app.py.

The order-processor service writes, reads, and deletes an orderId key/value pair to the statestore instance defined in the statestore.yaml component. As soon as the service starts, it performs a loop.

with DaprClient() as client:

    # Save state into the state store
    client.save_state(DAPR_STORE_NAME, orderId, str(order))
    logging.info('Saving Order: %s', order)

    # Get state from the state store
    result = client.get_state(DAPR_STORE_NAME, orderId)
    logging.info('Result after get: ' + str(result.data))

    # Delete state from the state store
    client.delete_state(store_name=DAPR_STORE_NAME, key=orderId)
    logging.info('Deleting Order: %s', order)

Step 3: View the order-processor outputs

Notice, as specified in the code above, the code saves application state in the Dapr state store, reads it, then deletes it.

Order-processor output:

== APP == INFO:root:Saving Order: {'orderId': '1'}
== APP == INFO:root:Result after get: b"{'orderId': '1'}"
== APP == INFO:root:Deleting Order: {'orderId': '1'}
== APP == INFO:root:Saving Order: {'orderId': '2'}
== APP == INFO:root:Result after get: b"{'orderId': '2'}"
== APP == INFO:root:Deleting Order: {'orderId': '2'}
== APP == INFO:root:Saving Order: {'orderId': '3'}
== APP == INFO:root:Result after get: b"{'orderId': '3'}"
== APP == INFO:root:Deleting Order: {'orderId': '3'}
== APP == INFO:root:Saving Order: {'orderId': '4'}
== APP == INFO:root:Result after get: b"{'orderId': '4'}"
== APP == INFO:root:Deleting Order: {'orderId': '4'}

statestore.yaml component file

When you run dapr init, Dapr creates a default Redis statestore.yaml and runs a Redis container 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 the state store without making code changes.

The Redis statestore.yaml file included for this quickstart contains the following:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: statestore
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: localhost:6379
  - name: redisPassword
    value: ""
  - name: actorStateStore
    value: "true"

In the YAML file:

  • metadata/name is how your application talks to the component (called DAPR_STORE_NAME in the code sample).
  • spec/metadata defines the connection to the Redis instance used by the component.

Pre-requisites

For this example, you will need:

Step 1: Set up the environment

Clone the sample provided in the Quickstarts repo.

git clone https://github.com/dapr/quickstarts.git

Step 2: Manipulate service state

In a terminal window, navigate to the order-processor directory.

cd state_management/javascript/sdk/order-processor

Install dependencies, which will include the @dapr/dapr package from the JavaScript SDK:

npm install

Verify you have the following files included in the service directory:

  • package.json
  • package-lock.json

Run the order-processor service alongside a Dapr sidecar.

dapr run --app-id order-processor --components-path ../../../components/ -- npm run start

The order-processor service writes, reads, and deletes an orderId key/value pair to the statestore instance defined in the statestore.yaml component. As soon as the service starts, it performs a loop.

  const client = new DaprClient(DAPR_HOST, DAPR_HTTP_PORT);

  // Save state into the state store
  client.state.save(STATE_STORE_NAME, [
      {
          key: orderId.toString(),
          value: order
      }
  ]);
  console.log("Saving Order: ", order);

  // Get state from the state store
  var result = client.state.get(STATE_STORE_NAME, orderId.toString());
  result.then(function(val) {
      console.log("Getting Order: ", val);
  });

  // Delete state from the state store
  client.state.delete(STATE_STORE_NAME, orderId.toString());    
  result.then(function(val) {
      console.log("Deleting Order: ", val);
  });

Step 3: View the order-processor outputs

Notice, as specified in the code above, the code saves application state in the Dapr state store, reads it, then deletes it.

Order-processor output:

== APP == > order-processor@1.0.0 start
== APP == > node index.js
== APP == Saving Order:  { orderId: 1 }
== APP == Saving Order:  { orderId: 2 }
== APP == Saving Order:  { orderId: 3 }
== APP == Saving Order:  { orderId: 4 }
== APP == Saving Order:  { orderId: 5 }
== APP == Getting Order:  { orderId: 1 }
== APP == Deleting Order:  { orderId: 1 }
== APP == Getting Order:  { orderId: 2 }
== APP == Deleting Order:  { orderId: 2 }
== APP == Getting Order:  { orderId: 3 }
== APP == Deleting Order:  { orderId: 3 }
== APP == Getting Order:  { orderId: 4 }
== APP == Deleting Order:  { orderId: 4 }
== APP == Getting Order:  { orderId: 5 }
== APP == Deleting Order:  { orderId: 5 }

statestore.yaml component file

When you run dapr init, Dapr creates a default Redis statestore.yaml and runs a Redis container 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 the state store without making code changes.

The Redis statestore.yaml file included for this quickstart contains the following:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: statestore
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: localhost:6379
  - name: redisPassword
    value: ""
  - name: actorStateStore
    value: "true"

In the YAML file:

  • metadata/name is how your application talks to the component (called DAPR_STORE_NAME in the code sample).
  • spec/metadata defines the connection to the Redis instance used by the component.

Pre-requisites

For this example, you will need:

Step 1: Set up the environment

Clone the sample provided in the Quickstarts repo.

git clone https://github.com/dapr/quickstarts.git

Step 2: Manipulate service state

In a terminal window, navigate to the order-processor directory.

cd state_management/csharp/sdk/order-processor

Recall NuGet packages:

dotnet restore
dotnet build

Run the order-processor service alongside a Dapr sidecar.

dapr run --app-id order-processor --components-path ../../../components/ -- dotnet run

The order-processor service writes, reads, and deletes an orderId key/value pair to the statestore instance defined in the statestore.yaml component. As soon as the service starts, it performs a loop.

var client = new DaprClientBuilder().Build();

// Save state into the state store
await client.SaveStateAsync(DAPR_STORE_NAME, orderId.ToString(), order.ToString());
Console.WriteLine("Saving Order: " + order);

// Get state from the state store
var result = await client.GetStateAsync<string>(DAPR_STORE_NAME, orderId.ToString());
Console.WriteLine("Getting Order: " + result);

// Delete state from the state store
await client.DeleteStateAsync(DAPR_STORE_NAME, orderId.ToString());
Console.WriteLine("Deleting Order: " + order);

Step 3: View the order-processor outputs

Notice, as specified in the code above, the code saves application state in the Dapr state store, reads it, then deletes it.

Order-processor output:

== APP == Saving Order: Order { orderId = 1 }
== APP == Getting Order: Order { orderId = 1 }
== APP == Deleting Order: Order { orderId = 1 }
== APP == Saving Order: Order { orderId = 2 }
== APP == Getting Order: Order { orderId = 2 }
== APP == Deleting Order: Order { orderId = 2 }
== APP == Saving Order: Order { orderId = 3 }
== APP == Getting Order: Order { orderId = 3 }
== APP == Deleting Order: Order { orderId = 3 }
== APP == Saving Order: Order { orderId = 4 }
== APP == Getting Order: Order { orderId = 4 }
== APP == Deleting Order: Order { orderId = 4 }
== APP == Saving Order: Order { orderId = 5 }
== APP == Getting Order: Order { orderId = 5 }
== APP == Deleting Order: Order { orderId = 5 }

statestore.yaml component file

When you run dapr init, Dapr creates a default Redis statestore.yaml and runs a Redis container 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 the state store without making code changes.

The Redis statestore.yaml file included for this quickstart contains the following:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: statestore
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: localhost:6379
  - name: redisPassword
    value: ""
  - name: actorStateStore
    value: "true"

In the YAML file:

  • metadata/name is how your application talks to the component (called DAPR_STORE_NAME in the code sample).
  • spec/metadata defines the connection to the Redis instance used by the component.

Pre-requisites

For this example, you will need:

Step 1: Set up the environment

Clone the sample provided in the Quickstarts repo.

git clone https://github.com/dapr/quickstarts.git

Step 2: Manipulate service state

In a terminal window, navigate to the order-processor directory.

cd state_management/java/sdk/order-processor

Install the dependencies:

mvn clean install

Run the order-processor service alongside a Dapr sidecar.

dapr run --app-id order-processor --components-path ../../../components -- java -jar target/OrderProcessingService-0.0.1-SNAPSHOT.jar

The order-processor service writes, reads, and deletes an orderId key/value pair to the statestore instance defined in the statestore.yaml component. As soon as the service starts, it performs a loop.

try (DaprClient client = new DaprClientBuilder().build()) {
  for (int i = 1; i <= 10; i++) {
    int orderId = i;
    Order order = new Order();
    order.setOrderId(orderId);

    // Save state into the state store
    client.saveState(DAPR_STATE_STORE, String.valueOf(orderId), order).block();
    LOGGER.info("Saving Order: " + order.getOrderId());

    // Get state from the state store
    State<Order> response = client.getState(DAPR_STATE_STORE, String.valueOf(orderId), Order.class).block();
    LOGGER.info("Getting Order: " + response.getValue().getOrderId());

    // Delete state from the state store
    client.deleteState(DAPR_STATE_STORE, String.valueOf(orderId)).block();
    LOGGER.info("Deleting Order: " + orderId);
    TimeUnit.MILLISECONDS.sleep(1000);
  }

Step 3: View the order-processor outputs

Notice, as specified in the code above, the code saves application state in the Dapr state store, reads it, then deletes it.

Order-processor output:

== APP == INFO:root:Saving Order: {'orderId': '1'}
== APP == INFO:root:Result after get: b"{'orderId': '1'}"
== APP == INFO:root:Deleting Order: {'orderId': '1'}
== APP == INFO:root:Saving Order: {'orderId': '2'}
== APP == INFO:root:Result after get: b"{'orderId': '2'}"
== APP == INFO:root:Deleting Order: {'orderId': '2'}
== APP == INFO:root:Saving Order: {'orderId': '3'}
== APP == INFO:root:Result after get: b"{'orderId': '3'}"
== APP == INFO:root:Deleting Order: {'orderId': '3'}
== APP == INFO:root:Saving Order: {'orderId': '4'}
== APP == INFO:root:Result after get: b"{'orderId': '4'}"
== APP == INFO:root:Deleting Order: {'orderId': '4'}

statestore.yaml component file

When you run dapr init, Dapr creates a default Redis statestore.yaml and runs a Redis container 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 the state store without making code changes.

The Redis statestore.yaml file included for this Quickstart contains the following:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: statestore
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: localhost:6379
  - name: redisPassword
    value: ""
  - name: actorStateStore
    value: "true"

In the YAML file:

  • metadata/name is how your application talks to the component (called DAPR_STORE_NAME in the code sample).
  • spec/metadata defines the connection to the Redis instance used by the component.

Pre-requisites

For this example, you will need:

Step 1: Set up the environment

Clone the sample provided in the Quickstarts repo.

git clone https://github.com/dapr/quickstarts.git

Step 2: Manipulate service state

In a terminal window, navigate to the order-processor directory.

cd state_management/go/sdk/order-processor

Install the dependencies and build the application:

go build

Run the order-processor service alongside a Dapr sidecar.

dapr run --app-id order-processor --components-path ../../../components -- go run

The order-processor service writes, reads, and deletes an orderId key/value pair to the statestore instance defined in the statestore.yaml component. As soon as the service starts, it performs a loop.

  client, err := dapr.NewClient()

  // Save state into the state store
  _ = client.SaveState(ctx, STATE_STORE_NAME, strconv.Itoa(orderId), []byte(order))
  log.Print("Saving Order: " + string(order))

  // Get state from the state store
  result, _ := client.GetState(ctx, STATE_STORE_NAME, strconv.Itoa(orderId))
  fmt.Println("Getting Order: " + string(result.Value))

  // Delete state from the state store
  _ = client.DeleteState(ctx, STATE_STORE_NAME, strconv.Itoa(orderId))
  log.Print("Deleting Order: " + string(order))

Step 3: View the order-processor outputs

Notice, as specified in the code above, the code saves application state in the Dapr state store, reads it, then deletes it.

Order-processor output:

== APP == dapr client initializing for: 127.0.0.1:53689
== APP == 2022/04/01 09:16:03 Saving Order: {"orderId":1}
== APP == Getting Order: {"orderId":1}
== APP == 2022/04/01 09:16:03 Deleting Order: {"orderId":1}
== APP == 2022/04/01 09:16:03 Saving Order: {"orderId":2}
== APP == Getting Order: {"orderId":2}
== APP == 2022/04/01 09:16:03 Deleting Order: {"orderId":2}
== APP == 2022/04/01 09:16:03 Saving Order: {"orderId":3}
== APP == Getting Order: {"orderId":3}
== APP == 2022/04/01 09:16:03 Deleting Order: {"orderId":3}
== APP == 2022/04/01 09:16:03 Saving Order: {"orderId":4}
== APP == Getting Order: {"orderId":4}
== APP == 2022/04/01 09:16:03 Deleting Order: {"orderId":4}
== APP == 2022/04/01 09:16:03 Saving Order: {"orderId":5}
== APP == Getting Order: {"orderId":5}
== APP == 2022/04/01 09:16:03 Deleting Order: {"orderId":5}

statestore.yaml component file

When you run dapr init, Dapr creates a default Redis statestore.yaml and runs a Redis container 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 the state store without making code changes.

The Redis statestore.yaml file included for this Quickstart contains the following:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: statestore
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: localhost:6379
  - name: redisPassword
    value: ""
  - name: actorStateStore
    value: "true"

In the YAML file:

  • metadata/name is how your application talks to the component (called DAPR_STORE_NAME in the code sample).
  • spec/metadata defines the connection to the Redis instance used by the component.

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.

Next steps

Explore Dapr tutorials >>