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