Alex,
The
current
answers to your questions re Example #1 is NO for both
- Will the terminationHandler of
scope "A" be activated?
- Should the compensation
handler of scope "B1SS1" be invoked? Which "handler" logic is
responsible to determine that?
The
flow is
completed successfully so A just proceeds, it is not terminated. This
is not a
problem, I believe this is what you intend for early completion.
The
premature
termination of a sequence does not involve any backward work, hence no
compensation for B1SS1. And if the branch were a scope this issue
would not
arise. But of course, scope can be used consciously by the process
designer if
one does not like this behavior. The question is, do we believe the
process
designer should be *forced*
to
express their intentions for premature termination handling explicitly
by enforcing
a scope boundary for each branch so that the termination behavior for
each
branch must be defined either by defining a termination handler or by
consciously choosing to omit it thereby invoking default behavior
(which would
then cause compensation for B1SS1). In other words the issue is not so
much “is
the behavior well-defined” — the issue is “should we protect
the naïve process designer from unintended pitfalls by enforcing a
scope
boundary for branches that may be prematurely terminated by early
completion”.
I
am so far
carefully avoiding expressing any opinions on this whole issue (issue
6) and I
will continue in that vein for the moment ;-)
Satish
Hi all,
Ivana and I were still discussing an open technical issue about this
6.2
proposal. That is: whether branches of <flow> should be
restricted to a
scope-based only when <completionCondition> / earlyCompletion is
used.
However, since there is a Apr 1st deadline for proposal submission, it
may be
better to submit the proposal on what was drafted so far without
waiting to
resolve this open issue. And, let other people comment on this open
issue.
Here is my detailed viewpoints and analysis we need a scoped-only
restriction
when early completion is used:
========================================================
Scope-based-only branches restriction for early completion is needed,
because:
- early completion mechanics
does not change fundamentally regardless whether we are using
<complete> activity or <completionCondition>
- we need a scope to encapsulate
activities of branch as "units of work" to minimize the need of
defining <completionHandler>
- a partial termination of a
scope is NOT well-defined in BPEL, while termination of the whole scope
is already well-defined in BPEL spec.
How termination mechanism
works in BPEL:
Here is my understanding of how the termination mechanism in BPEL
works:
When a scope is sent with a termination signal, the targeted scope
will: (1)
cascade the termination signal inner child scopes (2) stop all the
inner
activities within the targeted scope (3) execute the termination
handler. Then,
done.
As of now, the termination signal MUST alway go through a scope to
other
NON-scope activity. And, the termination Handler of the corresponding
scope
MUST got activated.
Hence, termination of the whole scope is well defined. However, a
partial
termination of a scope is NOT well-defined. That is we have not defined:
- what should happen if some
branches got terminated, while some branches are completed.
- what should happen if the
termination signal to sent to NON-scope activities without going
through a <scope>.
Example #1
Consider the following, a flow with two sequence as branches, which is
NOT
scope-based.
<scope
name="A">
<flow>
<completionCondition> ... </completionCondition>
<sequence
name="B1">
...
<scope name="B1SS1"> ... </scope>
<receive name="B1R2" ... />
...
</sequence>
<sequence
name="B2">
...
<scope name="B2SS1"> ... </scope>
<receive name="B2R2" ... />
...
</sequence>
</flow>
</scope>
Say, sequence "B2" finishes. The completionCondition is
fulfilled. Sequence "B1" is being terminated when it is waiting
a message at the receive "B1R2". Now, we got the
following questions unanswered, if we don't want to invent a brand
variation of termination mechanism:
- Will the terminationHandler of
scope "A" be activated?
- Should the compensation
handler of scope "B1SS1" be invoked? Which "handler" logic is
responsible to determine that?
Ok. Let's change it into scope-based branches.
<scope
name="A">
<flow>
<completionCondition> ... </completionCondition>
<scope
name="B1">
<terminationHandler> ... </terminationHandler>
<sequence>
...
<scope name="B1SS1"> ... </scope>
<receive name="B1R2" ... />
...
</sequence>
</scope>
<scope
name="B2">
<terminationHandler> ... </terminationHandler>
<sequence>
...
<scope name="B2SS1"> ... </scope>
<receive name="B2R2" ... />
...
</sequence>
</scope>
</flow>
</scope>
The above questions got answered clearly, with reusing the current
termination mechanism easily:
- Will the terminationHandler of
scope "A" be activated?
- Should the compensation
handler of scope "B1SS1" be invoked? Which "handler" logic is
responsible to determine that?
- It is up to the
terminationHandler to decide whether to invoke the compensation handler
of scope "B1SS1". By default, the terminationHandler of scope "B1" will
invoke that compensation handler.
Hence, we minimize the need of "completionHandler". I hope I have
refreshed your memory on why we come up with this scope-based branches.
(Regardless we use <complete> activity or not).
Example #2
One important to remember: <flow> only controls the parallelism
of
execution. It does not interfere the compensation and termination
structure of
a process.
Without scope-based-branch only restriction, the net effect of a
<flow>
is just a parallellized execution of activities inside the flow in an
undeterministic order. So, in one extreme case of this undeterministic
order,
one inner branch got completed first and then the other inner branch
got
executed. Hence, one extreme case of <flow> is equivalent to the
following nested sequence pattern in the context of compensation and
termination. (I replace <flow> in exmple #1 with an outter
<sequence> ... You can also think of one control-link is used
from
sequence "EX2B1" to "EX2B2").
--------------------------------
<scope
name="EX2A">
<sequence>
<sequence
name="EX2B1">
...
<scope name="EX2B1SS1"> ... </scope>
<receive name="EX2B1R2" ... />
...
</sequence>
<sequence
name="EX2B2">
...
<scope name="EX2B2SS1"> ... </scope>
<receive name="EX2B2R2" ... />
...
</sequence>
</sequence>
</scope>
--------------------------------
Say, the execution is waiting at receive "EX2B2R2". Now due to early
completion, we need to do this "partial" termination magic. We don't
have a well-defined way to terminate sequence "EX2B2" without
affecting sequence "EX2B1". Similarly, we don't have a well-defined
way to terminate sequence "EX2B2" without affecting
"EX2B2SS1"
Now think again, if we have scope-based-only branches, all activities
are
separated in units-of-work. Now those branches have independent
compensation
and termination structure now.
Last not least, if we map this early completion idea to transaction
world, it
does not seem like a good idea to allow partial transaction-work
rollback
(mapped to termination & compensation) without any units-of-work
boundary
marker or checkpoints (mapped to <scope>).
========================================================
Thanks!!!
Thank you so much for reading this long email!
Regards,
Alex Yiu
Trickovic, Ivana wrote:
Motivation
===========
The current semantics of the flow activity is that it completes when all
its (directly) nested activities have completed, either successfully or
unsuccessfully. However, there are scenarios where it is necessary to
have ability to complete the flow activity before all its nested
activities complete in order to speed up the process execution. For
example, a process waits in parallel for 3 reviews of a paper. If 2
positive reviews are received the process may continue with the
execution without waiting for the last, third response.
The completion condition of may have the following flavors:
* Wait for N out of M nested activities to complete
* Wait until after boolean condition C evaluates to true
The completion condition is interesting for a flow activity enclosing
identical nested activities and for the parallel for-each activity
(still under discussion).
Proposal
=========
Syntax:
<flow standard-attributes>
standard-elements
<links>?
<link name="ncname">+
</links>
<completionCondition>?
activity+
</flow>
<completionCondition>
<branches expressionLanguage="URI"?
countCompletedBranchesOnly="yes|no"?>
an-integer-expression
</branches>?
<booleanExpression expressionLanguage="URI"?>
a-boolean-expression
</booleanExpression>?
</completionCondition>
Semantics:
(1) The completionCondition element is an optional element of the flow
activity. Default behavior of the flow activity is that it waits for all
its nested activities to complete.
(2) There are two kinds of completion condition:
A> <booleanExpression>: A boolean condition operating upon process
variables. It is evaluated at the end of execution of each nested
activity.
B> <branches>: An integer value expression which is used to define
condition of flavor N out of M. It is evaluated at the end of execution
of each nested activity. This condition has "at least N out of M"
semantics. (The exact N out of M condition semantics involve resolving
racing condition among nested activities.)
(3) Both conditions (<branches> and <booleanExpression>) may be
specified at the same time. They will be evaluated at the end of
execution of each nested activity. If at least one condition evaluates
to true the <flow> activity completes successfully terminating all
remaining running nested activities. If both conditions are specified,
the <branches> will be evaluated first. If the boolean condition is
specified the evaluation of the condition is done in a serialized
fashion with respect to the nested activities directly enclosed in the
flow activity.
(4) If the integer value evaluated from the <branches> expression is
larger than the number of nested activities in the <flow>, then
bpws:invalidBranchCondition fault MUST be thrown. Note that the number
of branches may be known only during runtime in some cases. Static
analysis should be encouraged to detect this erroneous situation at
design time when possible. (E.g. when the branches expression is a
constant.)
(5) <branches> expression has an optional attribute
"countCompletedBranchesOnly". Its default value is "no". If
countCompletedBranchesOnly is "no", it means the BPEL processor will
count branches which have completed (either successfully or
unsuccessfully). If countCompletedBranchesOnly is "yes", it means the
BPEL processor will count branches which have completed successfully
only.
(6) If flow activity specifies a completionCondition element the
completion condition is evaluated each time a nested activity completes.
If the completion condition evaluates to true the flow activity
completes successfully. All still running nested activities will be
terminated.
(7) Standard BPEL termination semantics applies to running nested
activities when the completion condition is met. The termination of
running nested activities follows the termination semantics defined in
the specification (see section 13.4.4 Semantics of Activity
Termination).
(8) If all nested activities of the flow activity have been completed
but the completion condition evaluates to false the
"bpws:completionConditionFailure" MUST be thrown by the flow activity.
(end)
----------------
Ivana
---------------------------------------------------------------------
To unsubscribe from this mail list, you must leave the OASIS TC that
generates this mail. You may a link to this group and all your TCs in OASIS
at:
https://www.oasis-open.org/apps/org/workgroup/portal/my_workgroups.php