• This repository has been archived on 05/Mar/2020
  • Stars
    star
    100
  • Rank 340,703 (Top 7 %)
  • Language
    Ruby
  • License
    MIT License
  • Created over 15 years ago
  • Updated almost 5 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

RESTish wrapper for ruote workflow engine

ruote-kit (ruote on rack)

A wrapper around the ruote workflow engine, built as a modular Sinatra application.

Follow development:

Dependencies

ruote-kit uses Bundler to setup and maintain its environment. Before running ruote-kit for the first time you need to install Bundler (gem install bundler) and then run:

$ bundle install

Bundler will download all the required gems and install them for you.

Have a look at the Gemfile if you want to see the various dependencies.

Getting started quickly

Using the source

  • Get the source files using git
$ git clone http://github.com/kennethkalmer/ruote-kit.git
$ cd ruote-kit
  • Make sure every dependency is resolved
$ bundle install
  • Get going
$ bundle exec rackup

Using the RubyGem / Bundler

  • You'll need an empty directory
$ mkdir my-ruote-kit
$ cd my-ruote-kit
  • There are two files needed in that directory: Gemfile and config.ru

    • Gemfile
source :rubygems
gem 'ruote', :git => 'git://github.com/jmettraux/ruote.git'
gem 'ruote-kit', :git => 'git://github.com/kennethkalmer/ruote-kit.git'
  • config.ru

see for example https://github.com/kennethkalmer/ruote-kit/blob/master/config.ru

  • Install all needed gems
$ bundle install
  • Get going
$ bundle exec rackup

Accessing the web interface

If ruote-kit starts up without any issues (ie missing dependencies), you can point your browser to http://localhost:9292/_ruote/ to get going. By default ruote-kit binds to all IP addresses, so this works out the box remotely too.

Plugging ruote-kit into your rack-stack

ruote-kit is fully self-sufficient piece of rack, but can be slotted into any rack middleware stack without issues.

Example:

RuoteKit.engine = Ruote::Engine.new(
  Ruote::Worker.new(
    Ruote::FsStorage.new('ruote_work')))

RuoteKit.engine.register do
  catchall
end

# Slot into the stack
use RuoteKit::Application

Notes for Rails

ruote-kit ships with an application template for Ruby on Rails 3.

Generate a new Rails app using ruote[-kit]

  • install Rails
$ gem install rails
  • create a new Rails app by running
$ rails new foo -m https://github.com/kennethkalmer/ruote-kit/raw/master/rails-template.rb
  • cd into the new Rails dir
$ cd foo
  • make sure all dependencies are met
$ bundle install

Update an existing Rails app to use ruote[-kit]

  • in your Rails dir, apply the app template
$ rake rails:template LOCATION=https://github.com/kennethkalmer/ruote-kit/raw/master/rails-template.rb

Configure your ruote-kit integration

See config/initializers/ruote-kit.rb in your Rails app.

Run

$ rails server

Browse to http://localhost:3000/_ruote and you'll see there are no running processes. You could change that using the "Launch process" link ;-)

Using Ruote from within Rails

You can access Ruote's engine anywhere in your Rails code by calling

RuoteKit.engine

So launching a workflow process is as easy as

RuoteKit.engine.launch(your_process_definition)

The storage participant (used by the catchall participant) is available at

RuoteKit.storage_participant

Example application

See https://github.com/tosch/ruote-on-rails for an example Rails app.

Configuring ruote-kit & ruote

ruote-kit itself needs only little configuration, the only thing to do is to bind a ruote engine to use. That engine may be configured, see http://ruote.rubyforge.org/configuration.html for details.

When using the source version, you'll have to edit the config.ru file if you want to change the engine configuration. It defaults to use file system persistence and runs a worker within the engine. The persistence files will be stored in a sub directory called ruote_work_#{ENV}.

When using the gem version or plugging ruote-kit into your rack stack, you'll have to bind the ruote engine to use yourself. See the examples above.

Registration of participants

ruote participants may be registered using the register method of the engine. It expects a block containing of participant and one or less catchall calls.

RuoteKit.engine.register do
  participant 'no_op', Ruote::NoOpParticipant
  catchall
end

This example binds the identifier "no_op" to the Ruote::NoOpParticipant implementation.

The catchall is synonymous for

participant /.+/, Ruote::StorageParticipant

With such a definition and since it comes last, it means that all the workitems that are not for participant "no_op" end up in the storage participant. Thus

Ruote.define do
  concurrence do
    ceo
    no_op
    cto
  end
end

will route three concurrent workitems, one for "ceo" and one for "cto" to the storage participant (see the "workitems" tab in your ruote-kit interface) and one to "no_op", the no operation participant (which will reply immediately).

When playing initially with ruote-kit it's probably better to leave the registration block to:

RuoteKit.engine.register do
  catchall
end

So that all the workitems are placed in a storage participant.

If you want to learn more about ruote's participants, have a look at http://ruote.rubyforge.org/participants.html.

The workitems resource

The workitems resource relies on the Ruote::StorageParticipant. You'll have to register at least one Storage Participant if you ever want to see a workitem in the resource. Example:

    require 'ruote/part/storage_participant'
    RuoteKit.engine.register_participant :storage, Ruote::StorageParticipant

You may also use the catchall participant provided by ruote. It's named '.+', so it will catch all workitems for any participant mentioned in your workflow definitions which are not already caught by another (previously) registered participant. So make sure to register the catchall after your own participants. The catchall participant may be registered by calling catchall within the block given to Ruote::Engine#register (this will use Ruote::StorageParticipant as participant implementation, you may use any options of Ruote::Engine#register_participant to overwrite that default -- see the example above).

Running workers

Always make sure to have a running ruote worker for your storage. The shipped config.ru takes care of that, but if you use the gem version or use ruote-kit as part of your rack stack, you'll need to make sure there is a running worker.

Perhaps it's best to give some more explanations about the architecture of ruote here. Ruote's engine class is shallow, just a few methods that insert launch and reply orders in the storage and read it when querying for process statuses. You see: The storage is important, it is used as communications backend between the various parts of ruote. The engine class and the storage are not enough, though. The real work is done by one or more workers which query the storage for things to do.

(note: compared to a flow hardcoded in a set of controllers, ruote is very slow. After all, it "interprets" its flows. When processes are uniquely composed of tiny services (no human participants) ruote will lose any time. When human participants are involved, flows are as slow as the slowest human participants)

Ruote ships with one worker implementation and various storage implementations. Have a look at http://ruote.rubyforge.org/configuration.html#storage for an overview.

In the most examples above, the worker instance is bound to the engine which is given to RuoteKit.engine:

RuoteKit.engine = Ruote::Engine.new(
  Ruote::Worker.new(
    Ruote::FsStorage.new('ruote_work')))

That is fine, especially when there is only one instance of the app running or the storage implementation supports multiple workers, because if there is more than one instance of the app running, there will be more than one worker operating on the same storage.

If you want to use a storage implementation which doesn't support multiple workers (Ruote::FsStorage under Windows, for example), you should start a dedicated worker in its own instance. In config.ru (or whereever you configure the engine to be used by ruote-kit), instanciate the engine without a worker:

RuoteKit.engine = Ruote::Engine.new(
  Ruote::FsStorage.new('ruote_work'))

ruote-kit or your rack app will start with no problems, you may even launch processes, but they'll never show up under /_ruote/processes: There is no worker which processes the launch requests stored in the storage.

To run a worker you need to setup a worker script similar to the rake task example below:

require 'rake'
require 'ruote-kit'

desc "Run a ruote-kit worker"
task :ruote_kit_worker do

  RuoteKit.run_worker(Ruote::FsStorage.new('ruote_work'))
end

Make sure to configure the storage in the same way as in the rest of the application or you won't get what you expect ;-)

If you used the Ruby on Rails 3 template for 'installing' ruote-kit, a ruote:run_worker task is added automatically (in lib/tasks/ruote.rake).

You also should consider using a separate worker instance when you're running ruote-kit or your rack app in an environment like Passenger: You won't be sure the app runs all the time, so it's likely that scheduled events will be missed (better: triggered too late). If you don't want to start a separate worker process, configure Passenger in a way that your app won't be killed in a very long time (Passenger 3 provides an option to ensure one instance of the app won't be killed) and make sure your storage implementation supports multiple workers.

Feedback & bug reports

Feedback and bug reports are welcome on the mailing-list, or on the #ruote IRC channel at Freenode.net.

Please do not hesitate to come back with any feedback.

License

(The MIT License)

Copyright (c) 2009-2013 Kenneth Kalmer (Internet Exchange CC, Clear Planet Information Solutions Pty Ltd)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

libraries used

Many thanks to the authors and contributors

More Repositories

1

daemon-kit

Daemon Kit aims to simplify creating Ruby daemons by providing a sound application skeleton (through a generator), task specific generators (jabber bot, etc) and robust environment management code.
Ruby
538
star
2

powerdns-on-rails

Rails frontend for PowerDNS running MySQL or PostgreSQL backends
Ruby
189
star
3

safely

Wrap your Ruby code a loving, error reporting embrace
Ruby
47
star
4

ratpack

Simple HTTP to XMPP/AMQP bridge built on Sinatra
Ruby
46
star
5

ember-cli-nouislider

{{range-slider}} component for ember-cli powered by noUiSlider
HTML
43
star
6

activerecord-tableless-models

DEPRECATED: Please see https://github.com/softace/activerecord-tableless
Ruby
25
star
7

re-frame-semantic-ui-react-github-widget

Using semantic-ui-react with re-frame - sample project
Clojure
21
star
8

bind-dlz-on-rails

Rails interface to completely manage a BIND DLZ installation
Ruby
19
star
9

correlate

An experiment in expressing relationships between CouchRest documents and ActiveRecord models
Ruby
14
star
10

synaptein

synaptein is a Jabber switching daemon for translating from/to other protocols to XMPP
Ruby
10
star
11

ruote-activerecord

ActiveRecord persistence and participant for ruote
Ruby
9
star
12

chef-and-nagios-presentation

Chef & Nagios Presentation
7
star
13

smsinabox

Ruby wrapper & command line tools for the SMS in a Box Service (ZA)
Ruby
7
star
14

ratchet-ember

Experimenting with combining Ratchet & Ember
JavaScript
6
star
15

resque-web-passenger

A sample rack setup to show how to deploy resque-web in its own virtual host
Ruby
5
star
16

ruote-external-workitem

Thin wrapper class for Ruote workitems when used outside of the core engine
5
star
17

ruote-kit-client

Small client library that speaks JSON to ruote-kit and provides you with bpm bliss in return
Ruby
5
star
18

postini

The postini gem is a Ruby interface on top of the Postini SOAP API's (Early Access Program) and forms part of the postini4r project
Ruby
5
star
19

re-frame-semantic-ui-react-github-tabs

Passing around components with reagent and Semantic UI- sample code
Clojure
4
star
20

ruote-rest-rails-client

Extracted from a production app, this is one way to interact with ruote-rest from inside Rails
Ruby
4
star
21

docker-stack

Ruby
4
star
22

profittrailer-setup

Shell
4
star
23

connect.sh

Simple bash script to ease SSH access from a list of hosts
Shell
3
star
24

celluloid-smtp-sample

Simple example of an SMTP server with Celluloid::IO & EventMachine
Ruby
3
star
25

portage-overlay

Some additional comforts for my portage tree
2
star
26

jquery-copyfriendly

Unobtrusive jQuery plugin to place the text of any element in an invisible text field, making sure no unnecessary whitespace is copied with to the clipboard
2
star
27

kennethkalmer.github.com

My github page
2
star
28

mua-proxy

Transparent proxy server between MUA's (Mail User Agents) and POP3 servers
Ruby
2
star
29

dotfiles

My collection of dotfiles
Emacs Lisp
2
star
30

pillow

TODO: one-line summary of your gem
Ruby
2
star
31

lorem-app

Little shoes application leveraging the lorem gem
Ruby
2
star
32

rk-em-blues

Ruby
1
star
33

partyhat

Coming soon
Ruby
1
star
34

gh-profile-ioc

Use Ruby & Javascript together in a simple example of extreme "Inversion of Control"
JavaScript
1
star
35

rubyfuza-2013

Sample code for my Rubyfuza 2013 presentation on reusing your client-side JS on the server with V8/Rhino
Ruby
1
star
36

autotest-growl-remote

autotest-growl for pure network-based growls
Ruby
1
star
37

dockerfiles

Shell
1
star
38

dsl-stats

MWeb ADSL usage reports via Slack webhooks - pet project
Clojure
1
star