Index: openacs-4/packages/workflow/www/doc/fall-2003-extensions.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/www/doc/fall-2003-extensions.html,v diff -u -r1.3 -r1.4 --- openacs-4/packages/workflow/www/doc/fall-2003-extensions.html 9 Jan 2004 15:47:53 -0000 1.3 +++ openacs-4/packages/workflow/www/doc/fall-2003-extensions.html 23 Jan 2004 11:02:28 -0000 1.4 @@ -32,8 +32,25 @@ -
@@ -54,6 +71,32 @@ +
When triggered, all child cases with a case_state of 'active' are put into the 'canceled' state. All child cases have their 'locked_p' @@ -245,9 +289,534 @@ +
+---------------------------------------------------------------------- +-- Knowledge level +---------------------------------------------------------------------- +create table workflows( +); + +create table workflow_roles( +); + +create table workflow_actions( + action_id integer primary key + ... + parent_action_id integer references workflow_actions, + assigned_role integer references workflow_roles + trigger_type char(40) + constraint wf_case_enbl_act_trig_type_ck + check (trigger_type in ('user','auto','message','workflow','parallel','dynamic')), + ... +); + +create table workflow_fsm_states( + state_id integer primary key + ... + parent_action_id integer references workflow_actions +); + + +---------------------------------------------------------------------- +-- Operational level +---------------------------------------------------------------------- + +create table workflow_case_fsm( + case_id + action_id + state_id +); + +create table workflow_case_actions( + case_id integer references workflow_cases + action_id integer references workflow_actions + assigned_p boolean + execution_time timestamptz +); ++ +
+roles role_id + --------- + lawyer + client + +actions action_id | parent_action_id | assigned_role | trigger_type | new_state + --------------+------------------+---------------+--------------+--------------- + init | | | init | open + ask client | | | workflow | done + ac-init | ask client | | init | ac-asking + ac-ask | ask client | lawyer | user | ac-responding + ac-respond | ask client | client | user | ac-done + abort | | judge | user | done + +states state_id | parent_action_id + ---------------+------------------ + open | + done | + ac-asking | ask client + ac-responding | ask client + ac-done | ask client + +state_action_map state_id | action_id + ---------------+------------ + open | ask client + open | abort + ac-asking | ac-ask + ac-responding | ac-respond + +case_state action_id | state_id + ------------+--------- + | open + ask client | ac-asking + +case_enabled_actions ID | action_id | parent_enabled_action_id | assigned_p + ----+------------+--------------------------+------------ + #1 | ask client | | no + #2 | ac-ask | #1 | yes + #3 | abort | | no ++ +
+roles role_id + --------- + lawyer + client + +actions action_id | parent_action_id | assigned_role | trigger_type | new_state + ----------------+------------------+---------------+--------------+--------------- + init | | | init | open + rev & op | | | parallel | done + review-wr | rev & op | | workflow | + rev-init | review-wr | | init | rev-open + review | review-wr | lawyer | user | rev-done + opinion-wr | rev & op | | workflow | + opi-init | opinion-wr | | init | opi-open + opinion | opinion-wr | lawyer | user | opi-done + +states state_id | parent_action_id + ---------------+------------------ + open | + done | + rev-open | review-wr + rev-done | review-wr + opi-open | opinion-wr + opi-done | opinion-wr + +state_action_map state_id | action_id + ---------------+------------ + open | rev & op + rev-open | review + opi-open | opinion + +case_state action_id | state_id + ------------+--------- + | open + review-wr | rev-open + opinion-wr | opi-open + +case_enabled_actions ID | action_id | parent_enabled_action_id | assigned_p + ----+--------------+--------------------------+----------- + #1 | rev & op | | no + #2 | review-wr | #1 | no + #3 | review | #2 | yes + #4 | opinion-wr | #1 | no + #5 | opinion | #4 | yes ++ +
+ Difference between parallel sub-actions and non-parallel + sub-actions: If they are parallel, we enable all of them and don't + maintain state there; if they're not, we look for an init-action, + and do maintain state. +
+ ++actions action_id | parent_action_id | assigned_role | trigger_type | new_state +(workflow) ----------------+------------------+---------------+--------------+--------------- + init | | | init | open + ask client | | | workflow | done + ac-init | ask client | | init | ac-asking + ac-ask | ask client | lawyer | user | ac-responding + ac-respond | ask client | client | user | ac-done + abort | | judge | user | done + +actions action_id | parent_action_id | assigned_role | trigger_type | new_state +(parallel) ----------------+------------------+---------------+--------------+--------------- + init | | | init | open + rev & op | | | parallel | done + review-wr | rev & op | | workflow | + rev-init | review-wr | lawyer | init | rev-open + review | review-wr | lawyer | user | rev-done + opinion-wr | rev & op | | workflow | + opi-init | opinion-wr | lawyer | init | opi-open + opinion | opinion-wr | lawyer | user | opi-done ++ +
+ An action with type 'workflow' will maintain state inside itself. +
+ ++ Can we do away with the extra layer of 'workflow' inside the + 'parallel' track? How do we know that the child workflow has been + completed -- i guess we do, because we keep the state until its + parent is gone... +
+ ++actions action_id | parent_action_id | assigned_role | trigger_type | new_state +(parallel-simple) ----------------+------------------+---------------+--------------+--------------- + init | | | init | open + rev & op | | | parallel | done + review | rev & op | lawyer | user | + opinion | rev & op | lawyer | user | + + +states state_id | parent_action_id + ---------------+------------------ + open | + done | + +state_action_map state_id | action_id + ---------------+------------ + open | rev & op + +case_enabled_actions ID | action_id | parent_enabled_action_id | assigned_p | completed_p + ----+--------------+--------------------------+------------+------------- + #1 | rev & op | | no | no + #2 | review | #1 | yes | no + #3 | opinion | #1 | yes | no + ++ +
+ Simple: We'd have to keep the row in case_enabled_actions around + with completed_p = yes until the parent action is also + complete. When an action is completed, it deletes the rows for all + its children. If the action does not have a parent action, we delete + the row (thus we don't keep completed_p rows around for top-level + actions). +
+ ++actions action_id | parent_action_id | assigned_role | trigger_type | new_state +(dynamic-simple) ----------------+------------------+---------------+--------------+--------------- + init | | | init | open + all-votes | | | dynamic | done + vote | all-votes | voters | user | + +states state_id | parent_action_id + ---------------+------------------ + open | + done | + +state_action_map state_id | action_id + ---------------+------------ + open | all-votes + +case_enabled_actions enabled_action_id | action_id | parent_enabled_action_id | assigned_p | completed_p + -------------------+--------------+--------------------------+------------+------------- + #A | all-vote | | no | no + #B | vote | #A | yes | no + #C | vote | #A | yes | no + +case_action_assignees enabled_action_id | party_id + -------------------+---------- + #B | malte + #C | peter ++ +
+actions action_id | parent_action_id | assigned_role | trigger_type | new_state +(dynamic-workflow) ----------------+------------------+---------------+--------------+--------------- + init | | | init | open + all-votes | | | dynamic | voted + vote | all-vote | | workflow | + init | vote | | init | vote-voting + approve | vote | voters | user | vote-approved + reject | vote | voters | user | vote-rejected + withdraw | | submitter | user | withdrawn + +states state_id | parent_action_id + ---------------+------------------ + open | + vote-voting | vote + vote-approved | vote + vote-rejected | vote + +state_action_map state_id | action_id + ---------------+------------ + open | all-votes + vote-voting | approve + vote-voting | reject + +case_state enabled_action_id | state_id + --------------------+--------- + | open + #B | vote-voting + #E | vote-voting + +case_enabled_actions ID | action_id | parent_enabled_action_id | assigned_p | completed_p | assigned_role + ----+--------------+--------------------------+------------+-------------+--------------- + #A | all-votes | | no | no | + #B | vote | #A | yes | no | + #C | approve | #B | yes | no | + #D | reject | #B | yes | no | + #E | vote | #A | yes | no | + #F | approve | #E | yes | no | + #G | reject | #E | yes | no | + #H | withdraw | | yes | no | submitter + + +case_action_assignees enabled_action_id | party_id + -------------------+------------ + #B | malte + #D | malte + #F | peter + #G | peter ++ +
+ When a dynamic action is enabled, we create new enabled_action rows + for each of the child actions/workflows needed +
+ +
+state_changed_handler +-------------------- +- find all actually enabled actions + - chase the action-state-map for all current_states + - add children of enabled actions, where the child has always_enabled_p = true, + or the parent has trigger_type = parallel or dynamic. +- enable all new actions + +enable +------ +- if trigger_type = workflow, find and execute child action with trigger_type = init. +- if trigger_type = parallel, find subactions and ::enable them +- if trigger_type = dynamic, we'll need code to determine which children to ::enable, and how to create them + +execute_state_change +-------------------- +- if action.new_state not null + - if there's a state with the same parent_action_id as the action being executed, update that state with new_state + - otherwise insert row with new_state + +complete +-------- +- if action.parent_action_id not null + - set workflow_case_enabled_actions.completed_p = true + - call child_state_changed_handler -action_id $parent_action_id +- otherwise, delete row in workflow_case_enabled_actions + - delete all child rows + +child_state_changed_handler +--------------------------- +- trigger_type = workflow/parallel/dynamic: + - if there are no actions with parent_action_id = :action_id, completed_p = false, + then call ::action::execute on the parent action + + +calculating the actual state-action map (which we can do later, if we want to) +------------------------------------------------------------------------------ +- apply the state-action mapping table +- add always-enabled actions with parent_id to the states in which their parent is enabled (or all, if no parent) +- add actions with parent.trigger_type dynamic/parallel to states in which their parent is enabled ++ + +
+always_enabled_p +---------------- +- if parent_action_id is null, it means it's always enabled + +- if parent action is trigger_type workflow, it means it's enabled when its parent workflow is enabled. + -> ::enable it after starting the workflow, i.e. executing the initial action + -> will it stay enabled? + -> it will get disabled automatically by cascading delete when its parent is deleted + +- if parent action is trigger_type parallel, it has no meaning, all the parent's children will get enabled, anyway + +- if parent action is trigger_type dynamic, same shit, no semantics + + +How about the state_changed_handler only deals with state change at a particular parent_enabled_action_id level? + + ++ +
@@ -292,7 +861,7 @@ -
create table workflow_action_fsm_output_map( @@ -433,7 +1002,7 @@ -Conditional Transformation Based on Child Workflows
+Conditional Transformation Based on Child Workflows
create table workflow_outcomes( @@ -465,8 +1034,9 @@-Gated Actions
+Gated Actions
+Requirements
@@ -514,7 +1084,7 @@ -
Enable Condition Callback
+Enable Condition Callback
Action.CanEnableP -> (CanEnabledP): Gets called when an @@ -540,7 +1110,7 @@
-Non-User Triggered Actions
+Non-User Triggered Actions
Requirements
@@ -567,7 +1137,7 @@ -Resolution Codes
+Resolution Codes
Requirements
@@ -642,7 +1212,7 @@ -Assignment Notifications
+Assignment Notifications
Requirements
@@ -668,9 +1238,8 @@ +Assignment Reminders
-Assignment Reminders
-Requirements
@@ -690,9 +1259,8 @@ +
Trying to Sum Up
-Trying to Sum Up
-Logic to Determine if Action is Enabled
@@ -891,19 +1459,11 @@ -
NOTE: Cloning
-- We need to update the new_from_spec and generate_spec procedures to - output and parse all the new properties from this spec which get - implemented. -
+Timers (Implemented)
- -Implemented: Timers
-Requirements