processi

about processes and engines

resource lifecycle tuple

I came across this passage :

Moving from design to implementation, we need to think about the protocol in a slightly different way. In a resource-oriented distributed application, an application protocol can be thought of as a function of one or more resource life cycles and the business rules that connect these resources. Because of its resource-centric nature, the Restbucks service does not host an application protocol state machine. In other words, there’s no workflow or business logic for the application protocol as such. Rather, the service governs the life cycles of the orders and payments participating in the application protocol. Any workflows in the service implementation relate to resource life cycles, not the application protocol life cycle. While we’ve been explicit in modeling the business process as an application protocol state machine, we’ve been diligent in implementing it wholly in terms of resource state machines.

REST in practice, page 131, (emphasis mine).

 

I had to link that passage to this blog post :

The bottom line is that a business entity lifecycle represents some business logic that is “business process independent”. This is probably news to many of you and some of you might say that a BEL is a “long running process” but it is not. It is long running. It is a process in the sense of an operating system point of view (nearly), but it is not and will never be a “business process”. The business process is represented by the activities (human or automated) that advance the lifecycle of one or more business entities.

Lifecycle example, from Carnets de Bord

 

Written by John Mettraux

October 27, 2010 at 5:24 am

volute

Vos luttes partent en fumée
Vers des flûtes enchantées Et de cruelles espérances
Me lancent Des dagues et des lances En toute innocence

J’cloue des clous sur des nuages Un marteau au fond du garage
J’cloue des clous sur des nuages Sans échafaudage

volutes Alain Bashung (funny auto-translation)

 

This started out in a notebook. I wanted to do something about ‘state’ and ‘lifecyle’, something like a state machine for multiple objects or a rule system for families of resources.

It ended up as something that feels like the subset of an aspect oriented framework. Subset because in its most vanilla usage it only cares about calls to set methods, and there is no “before” (at first glance).

This Ruby gem is named volute. Here is an example of its usage :

require 'volute'

class Package
  include Volute

  attr_accessor :location
  attr_accessor :delivered
end

volute Package do
  # filters non Package instance out

  volute :delivered => true do
    # applies when delivered switches to true
    object.emit_invoice
  end

  volute :location do
    # filters out changes that are not for the :location attribute

    volute 'SFO' => :any, 'FRA' => :any do
      # SFO and FRA are our international hubs, for any package transiting from there,
      # initial 'international' tracking
      TrackingSystem.track_international(object)
    end
  end
end

The “include Volute” reworks the attr_accessor, and triggers the evaluation of the volutes on each set.

It’s not always necessary to include Volute. Here is a example of [business] rules derived from Ruleby (volute is very dumb compared to Ruleby, the example doesn’t do justice to that project).

Here is the diagnosis example with volute :

require 'volute'

class Patient

  attr_reader :name
  attr_accessor :fever
  attr_accessor :rash
  attr_accessor :spots
  attr_accessor :sore_throat
  attr_accessor :innoculated

  attr_accessor :diagnosis

  def initialize(name)
    @name = name
    @symptoms = {}
    @innoculated = false
  end

  def diagnose!
    Volute.apply(self) # trigger evalution of volutes
    return @diagnosis
  end
end

volute Patient do

  volute :fever => :high, :spots => :true, :innoculated => true do
    object.diagnosis = 'measles'
    over # prevent further evals
  end
  volute :spots => true do
    object.diagnosis = 'allergy (spots but no measles)'
  end
  volute :rash => true do
    object.diagnosis = 'allergy (rash)'
  end
  volute :sore_throat => true, :fever => :mild do
    object.diagnosis = 'flu'
  end
  volute :sore_throat => true, :fever => :high do
    object.diagnosis = 'flu'
  end
end

pat = Patient.new('alice')
pat.rash = true

puts "#{pat.name} : diagnosed with #{pat.diagnose!}"

pat = Patient.new('bob')
pat.sore_throat = true
pat.fever = :high

puts "#{pat.name} : diagnosed with #{pat.diagnose!}"

 

The readme for volute is quite extensive. There are a few examples included.

You’ve already seen the diagnosis one, it aimed at using volute for some mini rule engine (nothing fancy at all).

There is an example about a simple (kph = km/h) equation where each time an attribute is changed, other attributes get adjusted.

The light example simply keeps tracks of the last time an attribute got modified.

There is a book in a bookshop state machine example with a variation, to explore state volutes and transition volutes.

Note that state machines built with volute are incomplete, they know nothing about further transitions (could I even call them state machines ? Rather a ‘state transition system’).

Traffic could be fun : it tracks the state of two “lines” and adjust the colour of their lights according to the number of cars waiting. It’s more in line with the “multiple objects” goal I had initially (still here somehow, but examples with 1 class are smaller).

Not sure if it’s worth moving logic out of objects, but it is a fun experiment.

 

http://github.com/jmettraux/volute

 

Written by John Mettraux

October 12, 2010 at 7:28 am

ruote 2.1.11 released

ruote is an open source workflow engine implemented in Ruby.

It takes as input process definitions and interprets them. It routes work among participants according to the flow described in those process definitions. It can orchestrate ping pong matches as well.

The main motivation behind this release is Torsten being tired of advising people to use ruote edge (thanks Bundler) for their ruote-kit installs, ruote was more than ripe for a new release. This version includes the result of the feedback of numerous people, as the changelog can attest.

I’ll address here two aspects, one in ruote itself, and one on its periphery.

participant in a workflow

Up until now, participants were registered one by one (order of registration matters).

engine.register_participant 'reception', Acme::ReceptionParticipant
engine.register_participant 'support', Acme::SupportParticipant
engine.register_participant '.+', Ruote::StorageParticipant

Torsten came up with an idiomatic solution in ruote-kit, that was soon promoted to ruote itself :

engine.register do
  reception Acme::ReceptionParticipant
  support Acme::SupportParticipant
  catchall
end

All is well in a vanilla world were participants are all known at system startup. People were asking about adding participants on-the-fly. Ruote has always been able to do that :

engine.register_participant 'reception2', Acme::ReceptionParticipant, :site => 'two'

but our reception2 gets registered after the catchall participant, and thus might never receive any workitems. A solution would be to place the participant as second to last :

engine.register_participant(
  'reception2', Acme::ReceptionParticipant, :site => 'two', :position => -2)

But blindly inserting participants isn’t good. Ruote 2.1.11 has a new method for setting the participant list in a single batch :

engine.participant_list = [
  [ '^reception$', 'Acme::ReceptionParticipant', {} ],
  [ '^reception2$', 'Acme::ReceptionParticipant', { 'site' => 'two' } ],
  [ '^support$', 'Acme::SupportParticipant', {} ],
  [ '^.+$', 'Ruote::StorageParticipant', {} ]
]

Very rough, but full control.

ruote in kit

ruote-kit was kind of left behind at version 2.1.8. Torsten and I resumed its development and brought it to 2.1.11.

Ruote-kit is a web administration console for ruote. Kenneth Kalmer’s genius idea was to make it a rack middleware (component), so that it works standalone or fits nicely in a rails application, under /_ruote/

list of processesview on a process errorlist of participantsview on a workitem

Ruote-kit is more than a web administration console, it’s also an HTTP/JSON based interface to ruote, for example : http://gist.github.com/611044. The entry point of the interface is /_ruote/ all the resources are linked to from this “root”. The links are annotated with “rel” attributes that indicate to clients what stands behind the link.

There is more to it, we’re working on conveying the capabilities of both interfaces HTML / JSON from the HTML (the one that is easily navigated by a human and his browser).

storages got updates

ruote-dm, ruote-redis, ruote-couch have been upgraded to 2.1.11.

Note that there is a piece of documentation on how to implement storages that is in the works as it was requested by people who want to have a MongoDB backend.

next steps

Still have to release an updated ruote-amqp, and bring ruote-beanstalk to 2.1.11. Then it will be time to think about 2.1.12. As said, there is still work to do on ruote-kit, and since it’s used by many ruote people, it deserves full attention.

Many thanks to Eric Platon, Nathan Stults, Asier, Hartog de Mik, Brett Anthoine, Eric Smith, Kaspar Schiess, David Greaves, Rich Meyers, Kenneth Kalmer, Don French and David Goodlad (and many others) for their contributions !

source : http://github.com/jmettraux/ruote
mailing list : http://groups.google.com/group/openwferu-users
doc : http://ruote.rubyforge.org
irc : #ruote on freenode.net

 

Written by John Mettraux

October 5, 2010 at 6:07 am

amqp, ruote, pong

Hartog de Mik just wrote an investigation into ruote and AMQP. In this blog post, he makes the long jump from zero to ruote + RabbitMQ participants via the vaguely charted ruote-amqp territory.

But right before clicking away to Hartog’s blog post, please consider this pure ruote pong solution :

require 'rubygems'
require 'ruote'

pdef = Ruote.process_definition do
  repeat do
    ping # mister ping, please shoot first
    pong
  end
end

class Opponent
  include Ruote::LocalParticipant

  def initialize (options)
    @options = options
  end

  def consume (workitem)
    puts @options['sound']
    reply_to_engine(workitem)
  end
end

engine = Ruote::Engine.new(Ruote::Worker.new(Ruote::HashStorage.new))

engine.register_participant :ping, Opponent, 'sound' => 'ping'
engine.register_participant :pong, Opponent, 'sound' => 'pong'

wfid = engine.launch(pdef)

sleep 5 # five seconds of ping pong fun

engine.cancel_process(wfid) # game over

 

http://ruote.rubyforge.org (home)
http://groups.google.com/group/openwferu-users (mailing list)
IRC #ruote on freenode.net

 

Written by John Mettraux

September 27, 2010 at 2:24 pm

Posted in ruby, ruote, workflow

quaderno

My task as a programmer seems mostly to be throwing forms at knowledge workers. I fool myself in thinking that a workflow engine is the panacea when deciding when and what form to present the user.

Workflows are supposed to be adaptable, the forms at the emerged tips even more so. “Can you add a text field here ?”.

In workflow technology, there seems to be this grail where the business user is knowledgeable enough to modify a process definition, and knowledgeable enough to modify a form. Defining a process has a strong taste of programming, and form building hints at hierarchical data structures. It’s a struggle to get right either of them.

I came up with a javascript library named quaderno that takes as input a form template written in a DSL (minilanguage is perhaps a better appellation) and a data dictionary, renders the form, and then, when the user is done, produces the updated data dictionary.

This template :

tabs
  tab "general"
    text_input name
    text_input age
    select gender [male, female]
  tab "appointments"
    box appointments.*^
      date .date
      text_input .goal
      text_area .comment

Will produce a form that looks like :

The second tab is gathering data in an “appointments” array. The suffix .*^ indicates that elements of the array, can be added and removed (+ and – merged into a *) and reordered at will (^).

This is a sample output, once the user has entered his values and the produce() function of quaderno somehow got called :

{ "name": "Toto",
  "age": "33",
  "gender": "male",
  "appointments": [
    { "date":"2010/9/18", 
      "goal":"general checkup", 
      "comment": "(and tell him to quit smoking)" } ] }

This example is visible at http://ruote.rubyforge.org/quaderno/viewer.html?sample=3, there is also another sample at http://ruote.rubyforge.org/quaderno/viewer.html.

I use quaderno for highly adaptable forms, whether they are part of a workflow or not. Perhaps I should not say “adaptable”, but “I trust other people enough to let them modify the forms”.

(at first, I had wanted to have three modes, form use, form view and form edit, but the last mode was a bit hard to maintain and the result was awful to use and to look at. I had come up with something better in terms of edition with the initial version, but I couldn’t get to show the link between data and fields. This 3rd version of quaderno is a back to the basics version, with this tiny DSL that moves away from WYSIWYG and exposes the data/form structure)

Quaderno is a MIT licensed javascript library. It’s not a solution, it’s a tool.

http://ruote.rubyforge.org/quaderno/viewer.html
http://github.com/jmettraux/quaderno

 

Written by John Mettraux

September 22, 2010 at 5:28 am

Posted in dsl, javascript, ruote, workflow

rocking the enterprise with ruby

“rocking the enterprise with ruby” is the name of the talk given by Munjal Budhabhatti and Sudhindra Rao at the RubyKaigi 2010. Munjal and Sudhindra are two ThoughtWorkers and their customer is Rackspace. Maybe I shouldn’t say customer, but rather “partner”.

While browsing the RubyKaigi’s program, I had noticed that their talk mentioned “business rules” and I was thinking to myself “there are things in this talk to learn for me as a ruote developer”. I attended the presentation and was quite surprised to learn that they’re using ruote. They especially indicated they had a provision process driven by ruote that they shrinked from 4 days to 18 minutes.

The talk enumerates the many details in the application which covers IP (4 and 6) automation and DNS automation. They’ve been delivering continuously, they’re building on Ruby, Rails, Ramaze and many other lesser known gems (ruote included) and they’re releasing open source libraries.

They had a funny anecdote : they were looking for a gem about a certain aspect of IP addresses and they found it on github, … and the developer was in the next cubicle.

The video of “rocking the enterprise with ruby” is available as well as the presentation slides.

When the talk was over, it was good fun to go over to the two speakers and introduce myself. They explained to me what they liked about ruote and how they sold it to their team. Ruote seems to fit nicely in their services and DSLs. I hope to meet them again to learn more.

It was then time to attend the following talks of the kaigi. It was a great event, too much to cover.

 

Written by John Mettraux

August 30, 2010 at 1:49 am

Posted in ruby, rubykaigi, ruote, workflow

Houston.rb ruote presentation by Wes Gamble

During the last Houston.rb meeting, Wes Gamble talked about ruote. Here are his slides :

 

Wes does an excellent job at presenting the main concepts in ruote, process definitions, participants, workflow vs state management and so on. I’m lucky to have people evangelizing ruote as I’m a too much a “you don’t understand workflow ? You certainly don’t need ruote” type.

There was a funny coincidence : my friend Alain Hoang was visiting Houston at that time and he joined the meeting. Alain and I were co-workers when I started working on ruote. He helped me with the initial Rakefile and tamed rote to build an initial website for the project. He also came up with the initial suggestion for the rufus namespace idea.

Many thanks to Wes for his great presentation (and to Alain for all his help).

 

Written by John Mettraux

August 16, 2010 at 12:46 am

Posted in ruby, rufus, ruote, workflow