Now I got all the TestGraphs green by commenting the graphiz dependencies.

On Sun, Jan 21, 2018 at 3:33 PM, Stephane Ducasse
<stepharo.s...@gmail.com> wrote:
> I got all the WfTestFlow green.
> So now we can study the execution a bit better.
>
> On Sun, Jan 21, 2018 at 3:28 PM, Stephane Ducasse
> <stepharo.s...@gmail.com> wrote:
>> HI cedrick
>>
>>
>>> To solve this « pb », just create WADynamicVariable as a subclass of
>>> DynamicVariable already in Pharo.
>>
>> Ok I will do it. What is important is to *share* knowledge and code.
>> So I changed and publish the code in my branch to make
>> CurrentWorkflowManager an dynamic variable.
>> Before I just inherited from Object.
>> Now we get a version that can be loaded.
>>
>>
>> There are also missing part for the
>>> export/import in XML (should be easy to fix and Max propose to give the code
>>> - DOMBuilder and co.)
>>> I tried to start a booklet with Stephane but it is too complicated right
>>> now. Stephane started a simpler version.
>>
>> For now saving and loading is not important. :)
>>
>>
>>> I put below a summary of the reflexion/discussion I had with Max.
>>
>> Thanks.
>> Now you should publish your code.
>> I would have preferred to work from a working code. Because now it is
>> like poking in the dark.
>>
>> Cedrick what did you get running?
>>
>> Stef
>> Some comments below
>>
>>
>>> ========= INTRO
>>>
>>> What's missing compared to the full (proprietary) solution are user
>>> interfaces that were web based (Seaside \+ Magritte). Also, persistence was
>>> achived through Omnibase. References were removed but they are stil some
>>> disfunctionning. Moreover, the completion of activities were mainly manual
>>> and achieved through web interface (web forms). They are, for now, no real
>>> way to introduce different kind of activities like those being
>>> message-based, event-based, service-based.
>>>
>>> To evolve, one has to remove all dependancies to Omnibase and
>>> Magritte/Seaside.
>>>
>>> There are also important design decisions to ensure WfWorkflow being a
>>> powerful and extensible workflow management system for Pharo. To me there
>>> are 2 main tasks:
>>> - rethink persistence (process definition and orchestration, realization)
>>> => persistance is essential and was central to Aare. Beside removing
>>> Omnibase references (and implication of WfManagedObject), some of the
>>> application features were very dependant on the persistence (like logging,
>>> tracing process evolution). All of these features are to be thing again
>>> considering as much as possible a loosely coupled solution. A general
>>> purpose storage solution like Voyage could be used. At first, in image
>>> storage will be used to focus on the running aspects of the library.
>>> - rethink interaction
>>> => Designing a general interaction sub-system is probably the more
>>> challenging tasks. Aare was web based. We want workflow to be UI agnostic.
>>> Moreover, we want to associate  ,
>>> remove Magritte (replace UI or build an independant system based on
>>> Annoucement for instance)
>>
>>
>> Yes I agree. Now I would like to be able to
>> - define a super simple workflow: I picked sequence: start -> task1 -> task2
>> - execute it and script it resolution.
>>
>> I would like to understand the difference between frame and activation.
>>
>>> ========= RANDOM QUESTIONS AND ANSWER (in black me - below max)
>>>
>>> 1)
>>>
>>> The static definition of workflow is done through WfWorkflow, WfOutgoingEdge
>>> and WfSteps (+ WfConditions). The easy part :)
>>
>> Yes the easy part.
>> I started to add a test to cover his
>>
>>>
>>> The runtime aspect are achieved via WfActivation, WfWorkList,
>>> WfWorkflowHistory et WfWorkflowManager. More difficult to understand and
>>> make evolve.
>>>
>>> WfWorkflowHistory represents the different versions of a workflow, so it
>>> belongs to the static part.
>>
>> I saw and documented the interaction between a workflow history and
>> its workflows.
>>
>>
>> WfWorkflowManager managers workflow definitions
>>> (static) and activations (dynamic).
>>> WfFrame is also a part of the dynamic side, connecting activations to a
>>> workflow.
>>> Workflows are hierarchical, i.e. a step can have a sub workflow (see
>>> WfWorkflowLibrary>>simpleSubflow)
>>
>> Yes for now I do not want to understand this part.
>>
>>>
>>> 3)
>>>
>>> Going back to activations, here is my current understanding.
>>>
>>> Once a step is activated (all condition on Edges leading to are true - to
>>> evaluate outgoing conditions of a step, the step execution has to be
>>> complete first) , we get an activation instance (I’m not 100% sure how
>>> completion of an activity and outgoing conditions are managed).
>>>
>>> As far as I understand, a step can always be activated (e.g. manually).
>>> However, activating a step propagates the values of conditions on the edges
>>> to the next steps and their activations ("dead" or "alive"). Hence, an
>>> activation responds to #isAlive with true if at leat one incoming token was
>>> true ("alive") (see WfStep>>continueInFrame:fromStep:alive: and
>>> WfActivation>>isAlive). The conditions are evaluated once #complete is sent
>>> to the activation.
>>> Activation instances are created by two ways (slightly different for the
>>> start step), but generally they are created when a step receives tokens from
>>> the outgoing edges of an upstream activation (see
>>> WfStep>>continueInFrame:fromStep:alive:).
>>>
>>>
>>> On the exemple of BLActivationHistoryItem that you gave, I’m not sure if
>>> it’s an activation of a history item stored in the history (subclasss of
>>> WfHistory?).
>>>
>>> My idea was that it should represent a record for an activation (there might
>>> be multiple records for a single activation). So "HistoryItem" would be the
>>> general description of a record, of which "ActivationHistoryItem" is a
>>> special case for activations (I hope that makes sense).
>>>
>>>
>>> 4)
>>> Moreover I don’t see clearly the difference with a scheduler and a BP engine
>>> (they are at least really complementary). Do you see any ressemblance
>>> between Activation and ScheduledJob ?
>>>
>>> I actually would like to have a (simple) scheduler with the BP engine :)
>>>
>>> Well, it's certainly a matter of point of view. I would argue that an
>>> activation is something close to a "job". A "scheduled job" would be a more
>>> specific case of a "job", a job that is in a queue. An activation has no
>>> notion of scheduling but simply represents the idea of what happens when
>>> traversal between two nodes occurs. A scheduler would be one way of managing
>>> activations (WfWorklist seems pretty close to a scheduler, holding running
>>> and completed activations).
>>
>>
>> Too subtle for me.
>>
>>
>>> To me the scheduler right now is not really existing besides having a list
>>> of simultaneous/parralelized steps to realize (activated or not). Activated
>>> means currently being done.
>>>
>>> You're right, I think. The application that Workflow was designed for
>>> required manual interaction, hence there was no need for other methods of
>>> scheduling (e.g. by time or event).
>>>
>>>
>>>
>>> This activation role is about logging and interacting with responsible
>>> users. But it is more than that. It’s the actual job being done.
>>>
>>> Yes.
>>>
>>>
>>>
>>> 5)
>>>
>>> Concerning run time modification of a process. Is it true that we can modify
>>> a currently executed workflow (steps that are not yet activated ?) ? I think
>>> that is possible (an cool). When activated, it shouldn’t. Would you think it
>>> would be interesting to allow activations to be suspended/resume (frozen),
>>> cancelled ?
>>>
>>> The history of workflows consists of copies. The steps of a workflow
>>> reference the workflow they belong to. Therefore, while it is possible to
>>> modify a workflow, modifications do not impact running workflows, as the
>>> steps of that workflow continue to reference the previous version. The model
>>> suggests that it is ok to create a new version of a workflow but not to
>>> modify existing workflows.
>>
>> For now I would like to get a workflow running without modifying it
>>
>>
>>> The model does *allow* (in principle) to modify an existing workflow but I
>>> doubt that was the intention.
>>
>> I think that it was because else why to bother.
>>
>> However, I don't see why modifying an existing
>>> workflow has to be bad thing, as long as you can guarantee that only edges
>>> and steps are modified that have not yet been activated. That could open up
>>> some interesting possibilities.
>>> Cancellation of an activation could be very interesting. It would basically
>>> allow reversal of complex effects. Very nice idea! I'm not so sure though
>>> whether suspending makes much sense. Maybe when a step has the potential to
>>> take a long time for some operation. But then you may run into transaction
>>> problems. The nice thing about an activation at the moment is that it's
>>> atomic (in theory). But again, done right that could open up interesting
>>> possibilities.
>>>
>>>
>>>
>>> If a running process is modified, do we track its evolutions in
>>> WfWorkflowManager ?
>>>
>>> The modification of a workflow is indeed announced to WfWorkflowManager,
>>> yes. Workflow versions are stored in WfWorkflowHistory. For modifying a
>>> *running* workflow you will probably want to create a specific workflow
>>> manager for that, that does validation etc.
>>>
>>>
>>>
>>> The goal of history(s) are to log the realization of the process. But is it
>>> one of its aim to « replay » the process execution ?
>>>
>>> No. WfWorkflowHistory only stores the static definitions. However, the
>>> history of activations could be used to replay an execution (nice idea!).
>>>
>>>  i.o.w.,  Is it more than log/report ?
>>>
>>> I think the activation history was designed as a log, the workflow history
>>> as a log and also as a way to undo changes. As you suggest, however, they
>>> could certainly be used for more things.
>>>
>>>
>>> I agree with the separation (WfWFManager for the run time evolution of the
>>> process definition => adaptation    and WfActivationHistory for the trace of
>>> interactive/automatic step realizations information).
>>>
>>>
>>> #beginHistory implementation example was very helpful. I knew I missed
>>> something  Just, as I see a MailManager (with role is obvious), is it
>>> something that has to be generalizable ? Like InteroperableManager ?
>>> MessageManager ? To get user interactions
>>>
>>> That would be very nice, yes. You're completely free to do what you like. It
>>> would be cool though if we could evolve the project as opposed to you
>>> creating a fork to your own liking. If you're game we can set up a workflow
>>> on github where you open pull requests against our repository.
>>>
>>>
>>>
>>> 6) I’d like to remove fully the reference and need of Omnibase and
>>> Magritte/seaside forms.
>>>
>>> Yes please!
>>>
>>>
>>> I think Omnibase is ok, even storing in image for instance.
>>>
>>> What’s more problematic to me is for user interactions (and even automatic
>>> interaction through program for instance). There are achieved in your
>>> example with seaside. It is ok but what if I’d like to do it more generally
>>> ? Would we use Annoucement for example ?
>>>
>>> I think that is completely open to implementation. In my eyes, Workflow
>>> should remain a separate library that does not enforce any kind of specific
>>> presentation or persistence. What's critical for that is of course the right
>>> kind of interface.
>>> Announcements would certainly be an interesting way to decouple Workflow
>>> from other parts of the system.
>>>
>>>
>>> I’d like to have an incomingMessageBox for each user and eventually
>>> transform these message in concrete action (user i/o) ? Or dispatch in
>>> JobQueues (each user being a distant worker thread). Again, the distinction
>>> between Scheduler and BPEngin is fuzzy to me.
>>>
>>>
>>> Does it make sense to you ?
>>>
>>> Yes, it does :) What I've asked myself (out of curiosity) is whether you
>>> want to have
>>> - a dedicated instance for executing workflows
>>> - a distributed workflow with autonomous synchronisation (parts of a
>>> workflow could run on every uses instance, others would need to be executed
>>> through agreement)
>>> - a partially distributed workflow with one or more managing nodes that
>>> control the core steps (e.g. you could designate parts of a workflow as
>>> independant)
>>>
>>>
>>> PS: some random comments on your proposals
>>>
>>> Parts of Workflow were never cleanly separated from the proprietary
>>> application, so there are indeed a couple of things that are missing (mostly
>>> #subclassResponsibility stuff etc.)
>>>
>>>
>>>
>>> - initializeDefaults is not present for steps but thats ok.
>>>
>>>
>>> - in #createIncoming: (doesn’t exist), I don’t get ….. => makePersistent
>>> asPersistentReference.   You store persistentReference of steps. Is it like
>>> the step object itself ?  I would store the step objects (as no persistance
>>> right now).
>>>
>>> An activity step is a specific subclass of a step. Such a step includes
>>> additional information such as documents, duration and user roles. I'm not
>>> sure why "makePersistent asPersistentReference" is sent there, as WfStep
>>> already inherits from WfManagedObject and would, therefore, already be
>>> managed by OmniBase. But I don't know OmniBase, maybe some things need to be
>>> announced specifically.
>>>
>>>
>>> - I don’t understand the offsetSeconds in your BLActivationHistoryItem
>>>
>>> That's really just some business rule to modify the timestamp of the history
>>> item.
>>>
>>>
>>> ============= Others responses from Max
>>>
>>> WfWorkflow - Load and Run
>>> All instances that inherit from WfManagedObject were managed by OmniBase,
>>> yes.
>>> DomBuilder is a small package for wrapping XML-Parser. I'll publish it so
>>> you can use it.
>>
>> Cedric did you got this package?
>>
>>
>> The XML-Parser package has been significantly modified and
>>> is now named XMLParser (you can find it in the catalog). You should make the
>>> changes necessary to use the current incarnation of XMLParser (decide for
>>> yourself whether you still need DomBuilder or not).
>>
>> But this is not really important.
>>
>>>
>>>
>>> Those IDXXX classes belong to another package a didn't publish (but will).
>>> This package also includes an OmniBase specific class.
>>> Magritte has changed significantly over the years but the core should be
>>> pretty much the same. Just load the newest Magritte and try working with
>>> that.
>>>> ok but avoidable ?
>>>> try loading Magritte ?   Long …
>>>
>>> #beginInHistory should be implemented with #subclassResponsibility on
>>> WfActivation.
>>> Your explicit implementation could then look something like this:
>>> beginInHistory
>>> self history add: (MyActivationHistoryItem new
>>> message: 'started';
>>> user: (WACurrentSession value
>>> ifNotNilDo: [ :session | session user ]);
>>> type: #started;
>>> yourself).
>>> MyMailManager noteNewActivation: self
>>>
>>> Basically, what the history contains is up to the workflow implementation. I
>>> think it would makes sense though to have an abstract
>>> WfActivationHistoryItem.
>>> WfActivation>>history should be implemented like this:
>>> history
>>> ^self propertyAt: #history ifAbsentPut: [ OrderedCollection new ].
>>>
>>> Although I think that it would be good to have a dedicated
>>> WfActivationHistory class. WfWorkflowHistory is associated with changes to
>>> the workflow, not activations. Both history classes should probably inherit
>>> from an abstract class WFAbstractHistory.
>>>
>>>
>>> Seaside interaction
>>>
>>> Here are a couple of action implementations in Seaside components that
>>> should give you an idea of how to interact with the workflow:
>>> MyActivationComponent>>complete
>>> self activation hasCompleted
>>> ifTrue: [ ^ self ].
>>> self history add: (BLActivationHistoryItem new
>>> message: 'completed';
>>> user: self session user;
>>> type: #completed;
>>> offsetSeconds: -1;
>>> yourself).
>>> self activation complete.
>>>
>>> MyActivationForm>>accept: aString
>>> self activation authorized: true.
>>> self history add: (BLActivationHistoryItem new
>>> comment: aString;
>>> message: 'accepted';
>>> user: self session user;
>>> type: #accepted;
>>> offsetSeconds: -2;
>>> yourself).
>>> self completeIfSatisfied.
>>>
>>> MyActivityList>>addActivity
>>> self call: (MyActivityEditor new
>>> workflow: self workflow;
>>> yourself).
>>> self refresh.
>>>
>>> MyActivityEditor>>buildActivity
>>> ^(self workflow newActivityStep
>>> initializeDefaults;
>>> yourself)
>>> asPersistentReference.
>>>
>>> MyTransitionEditor>>createIncoming
>>> | step |
>>> step := (self workflow newActivityStep
>>> initializeDefaults;
>>> yourself) makePersistent asPersistentReference.
>>> self addIncoming: step.
>>> MyCurrentWorkflowComponent value showActivity: step.
>>>
>>> MyTransitionEditor>>addIncoming: anActivity
>>> ^self add: anActivity to: self activity.
>>>
>>> MyTransitionEditor>>add: aSourceActivity to: aDestinationActivity
>>> ^aSourceActivity addOutgoingEdgeFor: aDestinationActivity.
>>>
>>> MyTransitionEditor>>editCondtions: anEdge
>>> | component |
>>> anEdge condition isTrueCondition
>>> ifTrue: [ anEdge condition: WfAllCondition new ].
>>> component := (MyConditionEditor activity: self activity)
>>> container: anEdge;
>>> addDecoration: (MyToolbarDecoration new
>>> title: 'Edit Transition Conditions to: ' , anEdge to name;
>>> toolbar: [ :html |
>>> html
>>> icon: 'icon_close.gif'
>>> text: 'Close'
>>> action: [ component answer ].
>>> html helpIconOn: component ];
>>> yourself);
>>> yourself.
>>> self call: component.
>>>
>>> MyConditionEditor>>addRule: aDescription
>>> | new |
>>> new := MyCondition newPersistent
>>> field: aDescription;
>>> asPersistentReference.
>>> new := self call: (self
>>> buildEditorFor: new
>>> titled: 'Add Rule for ' , aDescription asLabel).
>>> new isNil ifFalse: [
>>> self condition add: new; markDirty.
>>> self changedForm ].
>>>
>>>
>>>> WfWorflowManager class is empty defining empty stubs/protocols. Its aim
>>>> seems to be about “logging/noting” changes. Is is it’s only role ?
>>> Correct. You would use WfWorkflowManager to update the workflow in OmniBase
>>> (e.g. mark dirty, add new activation etc.). #generateID would generate an ID
>>> from OmniBase and #activationClass would answer your specific activation
>>> class, if you choose to override WfActivation.
>>>

Reply via email to