Posted in:

I wrote recently about the benefits of adopting Dapr in a microservices application. In that post I focused on the "service invocation" building block. In this post, I want to highlight a particularly useful capability that is exposed by the "bindings" building block.

Dapr bindings

The concept of "bindings" in Dapr will be familiar to anyone who has worked with Azure Functions. They expose a simplified way of interacting with a wide variety of third party services.

Bindings can be "input" or "output". An input binding (also called a "trigger") allows Dapr to subscribe to events in external systems and call an endpoint on your service for you to let you know what has happened. Good examples in Azure would be subscribing to events on Event Grid or messages on Service Bus. But there are many supported bindings, including things like Twitter so you can get notified whenever something is tweeted matching your search criteria.

An output binding allows you to send data to an external service. In Azure this might be posting a message to a queue, writing a document to Cosmos DB. Or you could use it to send an SMS with Twilio.

Bindings benefits and weaknesses

One strength of bindings is that they can greatly simplify your application code as they remove a lot of the cumbersome boilerplate typically required to connect to the service.

Another advantage is that they provide a certain level of abstraction. Whilst some bindings can't be swapped out with other alternatives due to the service-specific nature of the data they deal with, the ability to swap out components has potential to be very useful in dev/test environments, where you may not want or need to actually communicate with a real service.

The key weakness of bindings is that they usually expose a fairly limited subset of capabilities of the underlying platform. So if you are a power user, then you may prefer to just use the SDK of the service directly. And of course Dapr doesn't prevent you from doing that - bindings are completely optional.

The cron binding

The binding I want to focus on particularly is a bit of a special case. It's the "cron" binding. Rather than supporting connection to an external system, this makes it easy to set up scheduled tasks.

To set this up, you need to define a component YAML file. You can just copy an example, and customise the schedule to meet your needs. This supports a regular cron syntax and some simplified shortcuts like @every 5m for every five minutes as shown below.

The only 'advanced' thing I've done is limited this component to only apply to a single Dapr service by using the scopes property - in this example the catalog service.

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: scheduled
  namespace: default
spec:
  type: bindings.cron
  version: v1
  metadata:
  - name: schedule
    value: "@every 5m"
scopes:
- catalog

Now all we need to do is listen on an endpoint that matches the name of our component. In this example it's called scheduled. Note that this will be made as a HTTP POST request, so in the example below I'm showing how a simple Node.js Express application can receive calls on the /scheduled endpoint and write a message to the console.

app.post('/scheduled', async function(req, res){
  console.log("scheduled endpoint called", req.body)
  res.status(200).send()
});

If we run this, we'll see that the /scheduled endpoint is called every five minutes by the Dapr sidecar.

And that's all there is to it. Of course, Dapr doesn't force you to use any of its building blocks, so if you already have a solution for scheduled tasks, then feel free to keep using it. But if not, it's great that Dapr provides such a simple to use option out of the box.

Want to get up learn more about how Dapr can greatly simplify the task of building microservices? Be sure to check out my Pluralsight course, Dapr 1 Fundamentals.