From zeta-dev-return-30-apmail-incubator-zeta-dev-archive=incubator.apache.org@incubator.apache.org Mon Jun 14 19:22:29 2010 Return-Path: Delivered-To: apmail-incubator-zeta-dev-archive@minotaur.apache.org Received: (qmail 25072 invoked from network); 14 Jun 2010 19:22:29 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 14 Jun 2010 19:22:29 -0000 Received: (qmail 77836 invoked by uid 500); 14 Jun 2010 19:22:29 -0000 Delivered-To: apmail-incubator-zeta-dev-archive@incubator.apache.org Received: (qmail 77777 invoked by uid 500); 14 Jun 2010 19:22:29 -0000 Mailing-List: contact zeta-dev-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: zeta-dev@incubator.apache.org Delivered-To: mailing list zeta-dev@incubator.apache.org Received: (qmail 77769 invoked by uid 99); 14 Jun 2010 19:22:29 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 14 Jun 2010 19:22:29 +0000 X-ASF-Spam-Status: No, hits=2.2 required=10.0 tests=HTML_MESSAGE,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (nike.apache.org: domain of marcel@blonk.org designates 69.93.155.28 as permitted sender) Received: from [69.93.155.28] (HELO gateway03.websitewelcome.com) (69.93.155.28) by apache.org (qpsmtpd/0.29) with SMTP; Mon, 14 Jun 2010 19:22:18 +0000 Received: (qmail 9563 invoked from network); 14 Jun 2010 19:26:44 -0000 Received: from gator336.hostgator.com (74.54.95.226) by gateway03.websitewelcome.com with SMTP; 14 Jun 2010 19:26:44 -0000 Received: from 97-113-184-133.tukw.qwest.net ([97.113.184.133]:63281 helo=[192.168.0.6]) by gator336.hostgator.com with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.69) (envelope-from ) id 1OOFEF-00084H-D2 for zeta-dev@incubator.apache.org; Mon, 14 Jun 2010 14:21:52 -0500 Message-ID: <4C168152.1000108@blonk.org> Date: Mon, 14 Jun 2010 12:21:54 -0700 From: Marcel Blonk User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.9) Gecko/20100317 Thunderbird/3.0.4 MIME-Version: 1.0 To: zeta-dev@incubator.apache.org References: <1276476844.47073.ezmlm@incubator.apache.org> In-Reply-To: <1276476844.47073.ezmlm@incubator.apache.org> Content-Type: multipart/alternative; boundary="------------070202060707000804000103" X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - gator336.hostgator.com X-AntiAbuse: Original Domain - incubator.apache.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - blonk.org X-Virus-Checked: Checked by ClamAV on apache.org Subject: [zeta-dev] Thoughts on workflow --------------070202060707000804000103 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Hi All, Recently I had a need for a workflow engine for our CakePHP based project. Even though we needed relatively straightforward document approval workflows, we decided to go with a workflow engine, because the separation of concerns allows for easy personalization of different workflows for different clients. After searching the web for the a bit, we found that ezComponents has by far the most well-developed open source PHP workflow engine. Integrating the workflow engine with CakePHP was not a big issue, as the workflow components is fairly separate from the rest of ezComponents, and the API of the workflow component is well thought out and easy to adapt (in short, thanks to the developers of ezComponents for desgining a great system!). Anyways, along the way I had to make several modifications to the workflow source code to accommodate the type of environment that I envisioned. I think a lot of the changes I had to make came from a different philosophy on how and where a workflow is instantiated. Correct me if I'm wrong, but it seems that's the default mode of instantiating a workflow is meant to be from code. This certainly is a valid way, but I prefer to write the workflow directly in XML. The changes I made to accommodate that are: * allow for string node IDs * do not rewrite/renumber node IDs * do not require IDs for nodes with only one input that are only connected with the node before it These 3 new rules make it much easier to write and debug workflows in XML. An example of readability improvement: before: after: Even for such a small example this makes it far more legible and easy to maintain (you can insert a node without having to renumber everything for example). It does impose a new rule that the order of nodes in the XML file matters. Other changes: * One need we had was that we wanted to present the user a choice based on the workflow state and available branches. Although this can be parsed in some way from the current node in the workflow (by traveling along the out notes until you get to a multiple-choice action), it makes things much more complicated than needed and imposes implicit restrictions to the workflow. For this I added a new action that has one input node and multiple (labeled) outputs and a method to get the list of those outputs. The action behaves as an input action and waits for a specified workflow variable and uses that value to determine what output to take. This allows you to load the current workflow state, and get the choices (if the current active node is our new action) to display to the user. Example: and then foreach($execution->getActivatedNodes() as $node) { if ( is_a($node,'ezcWorkflowNodeInputSplit') ) { $choices = array_merge($choices, $node->getChoices()); } } returns array( "Accept", "Reject") * We also found that using the threading paradigm made the workflow much more complicated if there are multiple intertwined loops in the workflow (e.g. send document back to previous reviewer or send the document back to originator in a review loop) but only one possible path. For that I made the above described new choice action not create new threads ($startNewThreadForBranch = false) and I added a converge action (same as simple merge, except assumes incoming nodes are all on the same thread). * I added a new variable node "VariableAppend" that appends an value to an (array) workflow variable. This allows you for example to accumulate comments in a review loop. eg. new comment * I added a variable type that is an indirect value, i.e. the value of the node is the name of a workflow variable, which allows you to assign one workflow variable with another. eg: assigns the value of workflow variable "two" to the workflow variable "one". This one is very useful when using XML-based workflows, as it is easier to vary the input of certain workflow actions (which otherwise would be hard coded in the XML). * I added a new optional label property to the node object (e.g. label="Waiting for review"). This allows you to label (input) nodes, so it becomes easy to display the current (wait) state of the workflow to the user by displaying the label of the currently active node. If there is any interest in any of these changes, I can of course make code available. One remaining issues I am still looking at and on which I could use advice, is the notion of a current user. Often a workflow involves handing the flow from one user to another. I added a current_user as a first class citizen to the execution state of a workflow, but it is of very limited use right now. A more generic notion of the current owner(s) of an execution (thread) would be useful, but I haven't come up with a good solution yet. Marcel --------------070202060707000804000103--