This part belong to a serie of articles about dapr :
- Introduction to dapr
- Service Invocation
- Publish-Subscribe pub/sub
- State management
- Hosting using AKS (Azure Kubernetes Services)
Distributed applications are composed of independent services. While each service should be stateless, some services must track state to complete business operations. Consider a shopping basket service for an e-commerce site. If the service can’t track state, the customer could loose the shopping basket content by leaving the website, resulting in a lost sale and an unhappy customer experience. For these scenarios, the state needs to be persisted to a distributed state store.
For that, we are going to add to our sample an example of a state store first using Redis .
Note: we are not going through best practices for creating a basket store for our website, we are just going to see how to use the state management.
in our last scenario, we have used the Service Invocation so our front app calls our API and so like that we get a list of cookies, now we are going to add an “Add” button in front of each cookie, and when the user clique on it, the ID of the cookie will be added to the basket (if you want to work on on the project you are welcome to contribute and add awesome stuff to it ).
First, let’s see what we are going to have :
You can download the source code from this link :
Now, how we work with state management.
How it works
First of all, and in order to work with the state we have to add a components folder that will contain few files that we are going to work with from state management to pub/sub and cron jobs.
Now , we need to create a yaml file : statestore.yaml .
ps: you can find the file when you install daper under : user\.dapr\components
apiVersion: dapr.io/v1alpha1 kind: Component metadata: name: redisstore spec: type: state.redis metadata: - name: redisHost value: localhost:6379 - name: redisPassword value: ""
The type of database is determined by the type
field, and things like connection strings and other metadata are put in the .metadata
section. Even though metadata values can contain secrets in plain text, it is recommended you use a secret store.
Here our store name is redisstore and we are going to use it later in our code sample.
Using the Dapr .NET SDK
Well as you may know it’s a combination of key/value ,this is how we store data here :
//saving a key of amount with data 5 await daprClient.SaveStateAsync<int> ("redisstore","amount",5); //getting the value using the key "amount" var amounttotal=await daprClient.GetStateAsync<int> ("redisstore","amount");
As you can see in the above sample, we are saving a combination of amount/5 and we are getting the value using the GetStateAsync method.
In our cookies sample, we want to save a list and its key is going to be CookiesList
var orderState = await _daprClient. GetStateEntryAsync<List<Item>>("redisstore", "CookiesList");
in order to get to the data from the store we should use the: GetStateEntryAsync, passing as parameters the name of the store that we early have configured in the statestore.yaml , also we pass the key and in our case is CookiesList.
public async Task<IActionResult> AdddataAsync(Guid ID) { Item _tem = new Item(); //getting the state var orderState = await _daprClient. GetStateEntryAsync<List<Item>>("redisstore", "CookiesList"); List<Item> CookiesList = new(); if (orderState.Value == null) { _logger.LogInformation("CookiesList Case not exist "); CookiesList.Add(_tem); await _daprClient.SaveStateAsync("redisstore", "CookiesList", CookiesList); } else { _logger.LogInformation("OrderState Case exist "); CookiesList = orderState.Value; CookiesList.Add(_tem); await _daprClient.SaveStateAsync("redisstore", "CookiesList", CookiesList); } ViewData["OrderId"] = ID; return View("Thanks"); }
in our sample here, we are receiving an ID from the page and creating a list of items that will contain the list of ID’s , in case the CookiesList exists we are adding the item to it else we are going to create it using the first method.
Now like that have made sure everything is alright, how can we explore or see if the store has been created and how to retrieve the value using the key.
Exploring Redis
Well, there are many ways to explore the Redis store here that we have created and we are going to see a couple of them.
Using Docker :
using this sample docker command we can get into the store :
Docker run --rm -it --link dapr_redis redis redis-cli -h dapr_redis
Now as we are inside the store, how can we see our keys/values?
simple using this command :
keys *
As you can see, we can see our cookies list here,now in order to explore it we need to use the following command :
HGET "cookiesclient||CookiesList" data
In order to delete key/value we should use :
del key "cookiesclient||CookiesList"
Using Visual studio code :
using visual studio code too we can explore the data after installing the Redis explorer plugin:
Also, there is other methods that we can use you can found them right here: https://docs.dapr.io/developing-applications/building-blocks/state-management/howto-get-save-state/
Retrieving the Data using the Dapr SDK
Now after we have saved our data to the store ,when we go to basket page we need to see the list of GUID that we have saved inside our list in order to get that list we should use :
var orderState = await _daprClient. GetStateEntryAsync<List<Item>>("redisstore", "CookiesList");
now if the order state.Value.Count>0 that means we have data inside it and we can get it like that and passe it to our view :
var orderList = orderState.Value;
Now in this part we have seen how to use the Save and get state using Redis , in the the Part 2 we are going to see how to use the Azure Cosmos DB as a backend state store .
Source code : https://bit.ly/3s5pz5C