fire-and-forget

After PHP and Node, we are happy to announce the public release of Zenaton’s Ruby library! 🎉 🎊

If you are curious as to how Zenaton can help you and your team, we will start with a quick recap of what Zenaton is and some of the vocabulary we use. Then, we will get your feet wet by having you run a couple of sample workflows through Zenaton.

Let’s dive right in! 🐬

dive-in

🗣 Talking the talk ️

Let’s start by defining a couple of common terms used throughout Zenaton:

  • Tasks can be either atomic operations such as sending an email, or waiting tasks such as idling for an amount of time, until a certain date, or until a given event happens.
  • Events are hooks you can define to trigger one or multiple tasks. An order being placed might be an example of an event.
  • Workflows are the control flows where you can define how tasks are executed (sequentially, in parallel, asynchronously, etc), and how events should be processed.

One of nice things about using Zenaton is that you can write any of these in the language you want: Ruby, JavaScript, PHP, Python and Go (with more languages coming soon 🙌). From your side, other than writing your workflows, all you have to do have your application start your workflows and have worker instances provisioned with Zenaton’s Agent to process them.

On the other side, Zenaton will take care of orchestrating tasks execution, abstracting away the message broker, managing the queues and persisting state. Additionally, we also provide you visibility into your workflows, with monitoring and tasks retrial through our dashboard.

overview-workflow-infra

For a more detailed presentation you can check some of our past articles:

Enough talking, let’s get down to it and run our very first workflows! 💪

workflow launching

🚶‍♀️Walking the walk

In order to follow this tutorial, you will need a Zenaton account. If you don’t already have one, head over to https://zenaton.com and sign up for one.

To get you up and running quickly, we have written a small collection of sample workflows, grab them by cloning zenaton/examples-ruby. From the root of directory run bundle install to install the required gems 💎. Now, copy the provided .env.example, edit it with your credentials (you can get them from your dashboard), and finally save it as .env.

Now we need to install the Agent. You have a couple of options:

  • Install it locally with curl https://install.zenaton.com | sh , which will auto-start the Agent. You can now tell it to listen for new workflows by typing zenaton listen --boot=boot.rb.
  • If your OS is not yet supported, such as Windows or some Linux flavours, you can run the Agent inside a Docker container 🐳. The repository contains one ready for consumption. Simply run docker-compose build; docker-compose up and you are good to go.

If you are eager to run your first workflow, simply execute from your terminal ruby launch_sequential.rb. You can see the output in zenaton.out.

Tip: to see the results as they come in, you may want to run either

tail -f zenaton.out

watch -n 1 cat zenaton.out

sequential workflow

If you want a closer look 🔎 at what is happening under the hood, let’s step through some of the different components. To create your own task , you will need to create a class that

  • inherits from Zenaton::Interfaces::Task.
  • includes the Zenaton::Traits::Zenatonable module, which will add some behaviours to allow us to orchestrate it.
  • implements an instance method handle, which is called when your task is executed by the Agent.
class TaskA < Zenaton::Interfaces::Task
  include Zenaton::Traits::Zenatonable

  def handle
    puts 'Task A starts'
    sleep 3 # Task takes some time to complete
    puts 'Task A ends'
    
    0 # The result of the task
  end
end

Similarly, to create your own workflow, the recipe is almost identical. The only difference being that Zenaton::Interfaces::Workflow should be the superclass your class inherits from.

class SequentialWorkflow < Zenaton::Interfaces::Workflow
  include Zenaton::Traits::Zenatonable

  def handle
    a = TaskA.new.execute # Let's store the return value from the task

    if a > 0 # And use that value to determine which task to run next
      TaskB.new.execute
    else
      TaskC.new.execute
    end

    TaskD.new.execute # This gets execute in either cases
  end
end

Finally, to launch your workflow

  • Initialize the client.
  • Instantiate your workflow and call dispatch on it. This method is provided by the Zenatonable module.
require 'zenaton'

Zenaton::Client.init(
  app_id, # You application ID
  api_token, # Your API token
  app_env # production, staging, development, or whatever you want
)

SequentialWorkflow.new.dispatch

For more details please you follow our tutorial from our website, which walks you through the various examples from the repository:

  • Run tasks one after the other: ruby launch_sequential.rb
  • Run tasks in parallel: ruby launch_parallel.rb
  • Run tasks asynchronously: ruby launch_asynchronous.rb
  • Send events to running workflows: ruby launch_event.rb
  • Tell a workflow to wait: ruby launch_wait.rb
  • Tell a workflow to wait for an event: ruby launch_wait_event.rb
  • Launch a workflow from another workflow: ruby launch_recursive.rb
  • Modify running workflows, allowing you to keep old ones running while deploying new versions at the same time: ruby launch_version.rb

Don’t be afraid to experiment 🔬 , and do share your findings with us. Here are a couple of ideas for you to try:

  • Stop the Agent ( zenaton stop ) during a workflow execution, then resume it ( zenaton start && zenaton listen boot=boot.rb ) , and see the execution pick up where it left off.
  • Check you dashboard to monitor your workflows, raise an error inside a task, see it fail on the dashboard, remove the exception from your task, relaunch the task from your dashboard, and see it finish successfully.

For more information, including how to integrate Zenaton with a Ruby on Rails application, check out our documentation. 📖

We hope that reading this will give your imagination some legs. We are curious about what you will come up with or how you might integrate Zenaton into an existing project. If you run into any troubles, have any questions, or want to give us some feedback, you can hit me up at igor@zenaton.com, file an issue on GitHub, or leave a comment 👇.

blow your mind