Workflow Maintainer's Guide

By Lars Pind on 27 July 2000.

OpenACS Documentation : Workflow : Workflow Maintainer's Guide


This document is about the internal details of the workflow package, aimed at developers maintaining the package.

System Overview

The workflow package consists of five major components:

Major components of the Workflow Package
Major components of the Workflow Package (open in separate window)

The Engine is the heart of the system. It's the part that determines what actions you can perform on a case, and keeps track of the state of the case as actions are performed. It also stores the process definitions and the state of all the cases on the system.

The Worklist is what the normal end-user sees. It's where the user goes to see the list of tasks he or she is assigned to, and interacts with the system to let us know he's done.

The Process Builder lets you define and share processes. The Process Adapter lets you customize assignments and special side-effects of your process to your situation. And finally, the Process Monitor lets you monitor the performance of a process.

Transitions and Tasks

When a transition becomes enabled, a row representing the enabled transition is inserted into wf_tasks. This table may have more than one row per transition for a number of reasons. If the user starts the task, then decides to cancel, a new row is inserted, as the same transition becomes enabled again. If there's an iteration in the workflow definition, so the same transition becomes enabled more than once, a new row is inserted each time.

Each task has a state. It starts out as 'enabled'. It moves to 'started', then possibly to 'canceled' or 'finished' in response to user actions. If the transition is part of an implicit or-split (where two transitions share one input place), the task may become 'overridden' if the other task is triggered.

Assignments

Assignments can be done in three different ways:
  1. Programmatic: You supply a callback to do the assignment. The callback will get called when the transition becomes enabled. Put the name of your callback in the assignment_callback column in wf_context_transition_info.

  2. Manual: Assignment for one case. This is implemented as rows in wf_case_assignments. You're encouraged to use the API: workflow_case.add_manual_assignment and workflow_case.clear_manual_assignments.

  3. Static: Fixed assignment for all cases of a given workflow. This is implemented as rows in wf_context_assignments table.
The actual assignment occurs when the transition is enabled. At that point, a row is inserted into wf_tasks and the actual assignment is determined, and copied over into wf_task_assignments. The logic is this:

  1. First, we see if there are any manual assignments in wf_case_assignments. If there is, we copy these over to wf_task_assignments. (We used to check for a callback first, but this way if a task is reassigned, the reassignment persists for subsequent instances of the transition.)

  2. If there are no manual assignments and a callback is registered, that callback procedure is executed, and is expected to use the workflow_case.add_task_assignment API to add the actual assignment for this task.

  3. Otherwise, we resort to the static assignment by copying over the rows from wf_context_assignments to wf_task_assignments.

In every event, a number of rows are created in wf_task_assignments. This is the authoritative version of who's assigned to this task. You're free to change the assignment of a task by altering the contents of wf_task_assignments through the API or directly. If you use the workflow UI, this change will be persistent. However, if you don't want reassignment to persist in your application, changing wf_task_assignments alone will accomplish this.

The view wf_user_tasks returns one row per task and per user assigned to a task. This is the view to query to get the list of tasks on a user's plate, and to get information about assignments for a task. It does the job of traversing the parties hierarchy to expand groups.

User Actions

Users can start, cancel and finish tasks. Since you can set workflow attributes as part of an action, for each of these actions, you have to make the following sequence of API calls:
  1. workflow_case.begin_task_action
  2. workflow_case.set_attribute_value zero or more times.
  3. workflow_case.end_task_action
(We would just accept a list of key/value pairs for the attributes, but we couldn't figure out a way to do that with PL/SQL).

The action argument to the procs are 'start', 'cancel', 'finish' or 'comment'. Comment doesn't alter the state of the task, and can be used for either adding a comment on the case, and/or to set a workflow attribute without finishing the task.

It's perfectly okay to finish a task without explicitly starting it. If there are multiple users assigned to the same task, however, it's strongly recommended that the user starts the task first, as that will remove it from the worklist of other users, so we don't have multiple users working on the same task.

Data Model Changes

Whenever there's a data model change, don't forget to propagate that change to:
lars@pinds.com
Last Modified: $Date: 2002/02/11 07:45:52 $