Skip to content

rubyists/dapr-ruby-client

Repository files navigation

Dapr Client for Ruby

Conventional Commits

Overview

This library provides an interface to the Dapr Building Blocks.

🔥
This is a work in progress and is not yet ready for production use.
ℹ️
Documentation will be added as this library matures.

Installation

Install the gem and add it to the application’s Gemfile by executing:

$ bundle add dapr --require dapr/client

If bundler is not being used to manage dependencies, install the gem by executing:

$ gem install dapr
Example from Gemfile
gem 'dapr', '~> 0.1.9', require: 'dapr/client'
gem 'datadog_api_client'
gem 'grpc', force_ruby_platform: true

Docker

If you find yourself waiting 20 minutes to build the grpc gem in your CI environments, you might want to use the images we publish (built from https://docker.io/library/ruby images)

Example Dockerfile
FROM ghcr.io/rubyists/dapr-ruby-client:0.3.0-ruby3.3.2-alpine3.20
RUN ...

Usage

Dapr being such a Smörgåsbord, this library exposes each Dapr Building Block as either a Client or a Service, depending on whether it uses the AppCallback runtime (Service) or the Dapr API (Client). The clients are thin wrappers around the Dapr API, while the service implementations will be more opinionated, higher-level abstractions. See the specific section on the building block you are interested in for its usage information.

Building Blocks

Namespace Convention

In order to avoid conflicts with any other Dapr top level namespace(s), Each Dapr Building Block is exposed as a class under the Rubyists::Dapr::Client or Rubyists::Dapr::Service namespace.

Pub/Sub

Implementation of Dapr Pub/Sub Building Block

Publish a message

require 'dapr/client/publisher'
ENV['DAPR_GRPC_PORT'] = '3500' (1)
publisher = Rubyists::Dapr::Client::Publisher.new('pubsub-name') (2)
publisher.publish('topic-name', { message: 'Hello, Dapr!', from: 'Ruby' }) (3)
  1. Set the Dapr gRPC port to the Dapr runtime port. (This is automatically set in kubernetes environments)

  2. Create a new publisher for the pubsub-name pubsub component. This component must be defined in the Dapr runtime.

  3. Publish a message to the topic-name topic. The message can be any Ruby object that can be serialized to JSON.

    💡
    JSON is our default serializer. To use a different serializer, you can pass a serializer: argument to the publisher’s initializer

Subscribe to topics

Subscriptions in Dapr work a little differently than you may be used to. Instead of subscribing to a topic then looping through consumed messages, you define a fully-fledged service that Dapr will send each message to in the topic(s) that you specify. This unique approach allows you to focus on the business logic of your service, rather than the plumbing of message consumption.

require 'dapr/service/subscriber'
handler = ->(event) { puts "Got event: #{event}" } (1)
pubsub_name = 'pubsub-name' (2)
topics = 'TOPIC-A' (3)
sub = Rubyists::Dapr::Service::Subscriber.new(pubsub_name:, topics:, handler:) (4)
sub.start! (5)
  1. Define a handler that will be called for each message received. event will be a CloudEvents::Event instance.

    ℹ️
    The handler can be anything that responds to #call, such as a lambda, proc, or instance. Sky’s the limit! (Dependency injection, anyone?)
  2. The name of the Dapr pubsub component this subscriber will utilize.

  3. The name of the topic(s) to subscribe to.

    💡
    Multiple topics can be subscribed to simultaneously by passing an array of topic names to the topics argument.
  4. Create a new subscriber for the pubsub-name pubsub component, subscribing to the TOPIC-A topic.

  5. Start the subscriber. This will block the current thread and call the handler for each message received.

State Management

Set state key(s)

require 'dapr/client/state' (1)
desired_state = { key1: 'value1', key2: { nested: 'value2' }.to_json } (2)
Rubyists::Dapr::Client::State.set(desired_state) (3)
  1. Require the state client.

  2. Define the desired state. This must be a hash with simple keys, and the values must be strings (thus the #to_json)

  3. Set the state. This will overwrite any existing state with the same key(s) (and update the etag of any updated keys)

Get state key(s)

require 'dapr/client/state' (1)
states = Rubyists::Dapr::Client::State.get('key1', 'key2') (2)
puts states['key1'].data (3)
  1. Require the state client.

  2. Get the state for the specified key(s). This will return a hash whose values respond to #data.

  3. Access the data of the state for the key1 key.

Actors

Implementation of Dapr Actor Building Block

Bindings

Implementation of Dapr Binding Building Block

Secrets

Implementation of Dapr Secret Building Block

Configuration

require 'dapr/client/configuration'
value = Rubyists::Dapr::Client::Configuration.get('TEST_KEY')

Distributed Lock

require 'dapr/client/lock'
lock = Rubyists::Dapr::Client::Lock.acquire('TEST_LOCK')
... do_important_stuff ...
lock.unlock!

Workflow

Implementation of Dapr Workflow Building Block

Cryptography

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem on your local machine, run bundle exec rake install.

Releases are handled by release-please in github actions.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/rubyists/dapr-ruby-client.

Conventional Commits

This project uses Conventional Commits for commit messages. Please follow the guidelines at conventionalcommits.org.

Overcommit

This project uses overcommit to enforce repository policies. Please ensure you have it installed and configured before contributing.

tl;dr;: overcommit --install && overcommit --sign