= Dapr Client for Ruby
:icons: font
ifdef::env-github[]
:tip-caption: :bulb:
:note-caption: :information_source:
:important-caption: :heavy_exclamation_mark:
:caution-caption: :fire:
:warning-caption: :warning:
endif::[]
:dapr-building-block: https://docs.dapr.io/concepts/building-blocks-concept/[Dapr Building Block]
:pubsub-block: https://docs.dapr.io/developing-applications/building-blocks/pubsub/pubsub-overview/[Dapr Pub/Sub Building Block]
:state-block: https://docs.dapr.io/developing-applications/building-blocks/state-management/state-management-overview/[Dapr State Management Building Block]
:actors-block: https://docs.dapr.io/developing-applications/building-blocks/actors/actors-overview/[Dapr Actor Building Block]
:binding-block: https://docs.dapr.io/developing-applications/building-blocks/bindings/bindings-overview/[Dapr Binding Building Block]
:secret-block: https://docs.dapr.io/developing-applications/building-blocks/secrets/secrets-overview/[Dapr Secret Building Block]
:configuration-block: https://docs.dapr.io/developing-applications/building-blocks/configuration/configuration-api-overview/[Dapr Configuration Building Block]
:distributed-lock-block: https://docs.dapr.io/developing-applications/building-blocks/distributed-lock/distributed-lock-api-overview/[Dapr Distributed Lock Building Block]
:workflow-block: https://docs.dapr.io/developing-applications/building-blocks/workflow/workflow-overview/[Dapr Workflow Building Block]
:cryptography-block: https://docs.dapr.io/developing-applications/building-blocks/cryptography/cryptography-overview/[Dapr Cryptography Building Block]
image::https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg[Conventional Commits,link=https://www.conventionalcommits.org/en/v1.0.0/]
== Overview
This library provides an interface to the {dapr-building-block}s.
CAUTION: This is a work in progress and is not yet ready for production use.
NOTE: 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
[source,ruby]
gem 'dapr', '~> 0.4', 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
[source,docker]
FROM ghcr.io/rubyists/dapr-ruby-client:0.4.2-ruby3.3.6-alpine3.21
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 {pubsub-block}
==== Publish a message
[source,ruby]
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.
+
TIP: 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.
[source,ruby]
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.
+
NOTE: 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.
+
TIP: 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
Implementation of {state-block}
==== Set state key(s)
[source,ruby]
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)
[source,ruby]
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 {actors-block}
=== Bindings
Implementation of {binding-block}
=== Secrets
Implementation of {secret-block}
=== Configuration
Implementation of {configuration-block}
[source,ruby]
require 'dapr/client/configuration'
value = Rubyists::Dapr::Client::Configuration.get('TEST_KEY')
=== Distributed Lock
Implementation of {distributed-lock-block}
[source,ruby]
require 'dapr/client/lock'
lock = Rubyists::Dapr::Client::Lock.acquire('TEST_LOCK')
... do_important_stuff ...
lock.unlock!
=== Workflow
Implementation of {workflow-block}
=== Cryptography
Implementation of {cryptography-block}
== 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 https://www.conventionalcommits.org/en/v1.0.0/[conventionalcommits.org].
=== Overcommit
This project uses https://github.com/sds/overcommit[overcommit] to enforce repository policies. Please ensure you have it installed and configured before contributing.
tl;dr;: overcommit --install && overcommit --sign