A DotNet Raider

My adventures in the .NET world!
posts - 49, comments - 12, trackbacks - 0

My Links

News

Website View Martino Bordin's profile on LinkedIn

Archives

Post Categories

Dapr - Input Binding and Configuration

Dapr binding is a mechanism that allows connections between components and external services by providing a common interface for communication, without needing to know about each other's implementation details.

It allows components to send and receive messages over a range of transport protocols and message brokers, like RabbitMQ and Kafka, Azure Event Grid, AWS SNS, Azure Service Bus, and Amazon SQS. You can also integrate with Twitter, SMTP, SendGrid, HTTP, or CRON.

Dapr has a building block also to manage and retrieve the application configurations (settings, connection strings, identifiers, etc) just by configuring the related component.

At the moment, the supported configuration stores are Redis, Postgres, and Azure App configuration.

Let's see how we can use both functionalities in the discount microservices.

No alt text provided for this image

First of all, we have to reference an additional NuGet package: Dapr.Extensions.Configuration

Once done, just go to the Program.cs file and add these lines of code, where we declare the config store and the list of keys we want to retrieve.

var builder = WebApplication.CreateBuilder(args

var client = new DaprClientBuilder().Build();
builder.Configuration     .AddDaprConfigurationStore(
       "redisconfigstore", 
       new List<string>() { "CrazyDiscountEnabled" }, 
       client, 
       TimeSpan.FromSeconds(20))     .AddStreamingDaprConfigurationStore(
       "redisconfigstore", 
       new List<string>() { "CrazyDiscountEnabled" }, 
       client, 
       TimeSpan.FromSeconds(20));)

Please note that AddDaprConfigurationStore will make the first call to load the config with the given keys, while AddStreamingDaprConfigurationStore will keep watching for changes and update local configurations.

Here's the main code of the discount controller:

[ApiController
[Route("[controller]")]
public class DiscountController : ControllerBase
{
	private readonly DaprClient daprClient;
	private readonly IConfiguration configuration;

	public DiscountController(
       DaprClient daprClient, 
       IConfiguration configuration)
	{
		this.daprClient = daprClient;
		this.configuration = configuration;
	}


	[HttpPost("/discountcronbinding")]
	public async Task<ActionResult> UpdateDiscount()
	{
		var crazyDiscountEnabled = configuration
                          .GetValue<bool>("CrazyDiscountEnabled");

		if (!crazyDiscountEnabled)
		{
			return Ok();
		}

		var random = new Random(Guid.NewGuid().GetHashCode());
		var discount = random.Next(1, 30);

		await daprClient.SaveStateAsync("redisstore", "CrazyDiscountValue", discount);
		return Ok();
	}


	[HttpGet]
	public async Task<int> GetDiscount()
	{
        var discount = 0;       
        var crazyDiscountEnabled = configuration
                          .GetValue<bool>("CrazyDiscountEnabled");      
        if (crazyDiscountEnabled)         
        {   
           discount = await daprClient
                   .GetStateAsync<int>("redisstore", "CrazyDiscountValue");         
        } 
 
         return discount;
	}
}]

We have a standard API Controller where we inject the DaprClient and the standard IConfiguration object that allows us to retrieve the settings.

The UpdateDiscount method checks if the configuration with the key CrazyDiscountEnabled is enabled. If yes, we're going to generate a random discount and save it using the state management we already know.

How is configured the Config store? Using the component specification, of course!

apiVersion: dapr.io/v1alpha
kind: Component
metadata:   name: redisconfigstore
spec:   type: configuration.redis   metadata:   - name: redisHost     value: redis:63791


As you can see we're connecting to Redis, so we can enable the crazy discount feature by running the following command in the Redis CLI

SET CrazyDiscountEnabled true

Now the random discount calculation is enabled, but when and who is calling this API?

We're going to use the CRON input binding, which will trigger a POST request based on the CRON expression we specify.

Here is our configuration:

apiVersion: dapr.io/v1alpha
kind: Component
metadata:   name: discountcronbinding
spec:   type: bindings.cron   version: v1   metadata:   - name: schedule     value: "* * * * * *"

We set the CRON expression in order to trigger every second. The POST will call a method with the same name as the binding (discountcronbinding in our case). So, basically, we're calculating a new random discount every second (if enabled by config).

We can retrieve the current valid discount just by performing a GET request to the Discount endpoint.

No alt text provided for this image

In the next article, we'll see the Pub\Sub building block.

Print | posted on martedì 10 ottobre 2023 10:37 | Filed Under [ Dapr Microservices ]

Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET