RIFE/Workflow
overview
RIFE/Workflow is a small prototype of a workflow engine with native Java continuations that can easily be distributed using Terracotta.
The design is simple, you create Task classes that contain the logic in an 'execute(TaskRunner)}' method. Inside that method, you can suspend the execution by using the '{{waitForEvent(EventType)' method. Note that this will not keep the executing thread running but creates a continuation in memory instead. This reduces resource starvation since threads are only running for tasks that are really executing logic. When 'waitForEvent' returns, you'll receive the event instance that was triggered and you can use the data it contains.
building it
RIFE/Workflow can be retrieved from its Subversion repository:
http://svn.rifers.org/rife-workflow/trunk/
To create a jar file with the RIFE/Workflow features, execute:
The javadocs can be generated with:
the included tests
The tests directory contains a basic example with two tasks that are each one waiting for one particular event type and are triggering events that the other one is waiting for. The first one, TaskType1, loops 20 times, thus triggering events of type TestEventType.TYPE2 twenty times and also waiting twenty times for events of type TestEventType.TYPE1. TaskType2, does the opposite but only loops 10 times. So, in practice, you need to run two instances of TaskType2 for each instance of TaskType1 to have them all complete their execution. You can see how this is done in the test class 'com.uwyn.rifewf.tests.TaskTest'.
To run the tests, execute:
distributed workflow tasks
Workflow tasks can easily be distributed using Terracotta 2.4 and later. The distribution can be downloaded from http://terracotta.org
. Once installed, you can compile the code that makes it easy to test this out by executing:
This basically creates two Java applications: Node1 and Node2. All they do is respectively starting instances of tasks TaskType1 and TaskType2 and wait until their execution is finished. Inside the 'terracotta' directory, you'll find a tc-config.xml file that should be applicable to any RIFE/Workflow application. This basically sets up which state of your application has become shared across multiple nodes and how the synchronization should be coordinated.
To run the test tasks on multiple nodes you have to do this:
1. start the Terracotta server:
- open a terminal
- cd into the Terracotta installation
- execute:
$ ./bin/start-tc-server.sh
2. start the first task on a first node:
- open a new terminal
- cd into the rife-workflow directory
- execute:
$ export TC_INSTALL_DIR=<your terracotta installation dir>
$ ./bin/tcnode1.sh
3. start the first instance of the second task on a second node:
- open a new terminal
- cd into the rife-workflow directory
- execute:
$ export TC_INSTALL_DIR=<your terracotta installation dir>
$ ./bin/tcnode2.sh
You'll see this execution finishes since all the events that TaskType2 is waiting for have been provided by TaskType1, and TaskType2 already provided 10 out of the 20 events that TaskType1 is waiting for.
4. start the second instance of the second task on a third node:
<idem to step 3>
You'll see that the execution on all nodes terminates. Something worth noting is that you see the following output in your last terminal:
The last execution of TaskType1 was thus actually performed in the JVM that was launched on the third node. Also, the event listener that was waiting for this task to finish on your first node received the proper END event and stops waiting. This clearly shows that threads migrate across nodes through continuations and that event dispatching is properly done over the cluster.
conclusion
I hope that this simple demonstration and example gets you excited about what is possible with Terracotta, RIFE/Workflows and RIFE's native Java continuations.
Feel free to visit our project sites for more information:
http://terracotta.org
http://rifers.org