Windows workflow 4 : difference between WorkflowApplication Cancel, Terminate and Abort - workflow-foundation-4

Can any one explain what the difference is between the following methods of WorkflowApplication:
Abort
Cancel
Terminate

After further investigating this issue, I want to summarize the differences:
Terminate :
the Completed event of the workflow application will be triggered
the CompletionState (WorkflowApplicationCompletedEventArgs) is Faulted
the Unloaded event of the workflow application will be triggered
the workflow completes
OnBodyCompleted on the activity will be called
Cancel:
the Completed event of the workflow application will be triggered
the CompletionState (WorkflowApplicationCompletedEventArgs) is Cancelled
the Unloaded event of the workflow application will be triggered
the workflow completes
OnBodyCompleted on the activity will be called
Abort:
the Aborted event of the workflow application will be triggered
the workflow does not complete
An unhandled exception
triggers OnUnhandledException
in this eventhandler the return value (of type UnhandledExceptionAction) determines what will happen next:
UnhandledExceptionAction.Terminate will terminate the workflow instance
UnhandledExceptionAction.Cancel will cancel the workflow instance
UnhandledExceptionAction.Abort will abort the workflow instance
Each will trigger the corresponding events explained above
Update: Abort does not seem to trigger unloading of the instance in the SQL persistence store. So it seems to me, you better use Cancel or Terminate and if you have to perform some action based upon the completion status, you can check CompletionState in the Complete event.

First, hats off to Steffen Opel (and his comments below). I failed to catch that my original post linked documentation that was WF 3.5 specific. Did a little more digging around.
For posterity's sake, I have left my previous response below, labelled as WF3.5. Please see WF4.0 for a few notes regarding Canceling, Abort, and Terminate in WF4.0.
WF4.0
Unfortunately, there is little explicit documentation discussing differences in Cancel, Abort, and Terminate in WF4.0. However, from member method documentation,
On Abort, a) activity is immediately halted, b) Aborted handler is invoked, and c) Completed handler is not invoked.
On Cancel, a) activity is given a grace period to stop gracefully after which a TimeoutException is thrown, b) Completed handler is invoked.
On Terminate, a) activity is given a grace period to stop gracefully after which a TimeoutException is thrown, b) Completed handler is invoked.
The differences between Abort and Cancel/Terminate is quite striking. Simply call Abort to kill a Workflow outright. The difference between Cancel and Terminate is more nuanced. Cancel does not require any sort of reason (it is a void parameterless method), whereas Terminate requires a reason (in either string or Exception format).
In all cases, Workflow runtime will not perform any implicit action on your behalf (ie Workflows will not auto-self destruct a la WF3.5 Terminate). However, with the highly customizable exception\event handling exposed by the runtime, any such features may be implemented with relative ease.
WF3.5
Canceling
According to Msdn documentation
An activity is put into the Canceling state by a parent activity explicitly, or because an exception was thrown during the execution of that activity.
While Canceling may be used to stop an entire Workflow (ie invoked on root Activity), it is typically used to stop discrete portions of a Workflow (ie either as error-recovery or an explicit action on part of parent). In short, Canceling is a means of Workflow control-flow.
Abort and Terminate
Again, according to Msdn documentation
Abort is different from Terminate in that while Abort simply clears the in-memory workflow instance and can be restarted from the last persistence point, Terminate clears the in-memory workflow instance and informs the persistence service that the instance has been cleared from memory. For the SqlWorkflowPersistenceService, this means that all state information for that workflow instance is deleted from the database upon termination. You will not be able to reload the workflow instance from a previously stored persistence point.
Which is pretty clear in itself. Abort merely stops in-memory execution whereas Terminate stops in-memory execution and destroys any persisted state.

Related

How to cancel a deferred Rebus message?

I am considering using deferred messages as a delay/timeout alerting mechanism within my Saga. I would do this by sending a deferred message at the same time as sending a message to a handler to do some time-consuming work.
If that handler fails to publish a response within the deferred timespan the Saga is alerted to the timeout/delay via the deferred message arrival. This is different to a handler failure as its still running, just slower than expected.
The issue comes if everything runs as expected, its possible that the Saga will complete all of its steps and you'd find many deferred messages waiting to be delivered to a Saga that no longer exists. Is there a way to clean up the deferred messages you know are no longer required?
Perhaps there is a nicer way of implementing this functionality in Rebus?
Once sent, deferred messages cannot be cancelled.
But Rebus happens to ignore messages that cannot be correlated with a saga instance, and the saga handler does not allow for that particular message type to initiate a new saga, so if the saga instance is gone, the message will simply be swallowed.
That's the difference between using IHandleMessages<CanBeIgnored> and IAmInitiatedBy<CannotBeIgnored> on your saga. 🙂

DB Transaction and Integrations Events dispatch - how to make it atomic?

I'm designing a system with multiple bounded contexts (microservices). I will have 2 kind of events.
Domain Events, which happens "in memory" within single transaction (sync)
Integration Events, which are used between bounded contexts (async)
My problem is, how to make sure that once transaction is committed (at this point I'm sure all Domain Events were processed successfully) that Integration Events are successful as well.
When my Transaction is committed, normally I will dispatch Integration Events (e.g. to the queue), but there is possibility that this queue is down as well, so previously just-committed transaction has to be "reverted". How?
The only solution that comes to my mind is to store Integration Events to the same DB, within the same Transaction, and then process the Integration Events records and push them to the queue - this would be something like "using current DB, as a pre-queue, before pushing it to The Real Queue (however I read that using DB for this is an anti-pattern).
Is there any pattern (reliable approach) to make sure both: Transaction commit and Message pushed to the queue is an atomic operation?
EDIT
After reading https://devblogs.microsoft.com/cesardelatorre/domain-events-vs-integration-events-in-domain-driven-design-and-microservices-architectures/ , the author actually suggests the approach of "pre-queue" in same DB (he calls it “ready to publish the event”).
Checkout transactional outbox pattern.
This pattern does create a pre-queue. But the nice part is that pushing messages from pre-queue to real queue is fully decoupled. Instead you have a middleman called, a message relay that reads your transaction logs and pushes your event from to the real queue. Now since sending message and your domain events are fully decoupled, you can do all your domain events in a single transaction.
And make sure you that all your services are idempontent(same result despite duplicate calls). This transactional outbox patter does guarantee that messages are published, but in case when the message relay fails just after publishing(before acknowledging) it would publish the same event again.
Idempotent services is also necessary in other scenarios. As the event bus(the real queue) could have the same issue. Event bus propagates events, services acknowledge, then network error, then since the event bus is not acknowledged, the same event would be sent again.
Hmm actually idempotence alone could solve the whole issue. After the domain events computation completes(single transaction), if publishing message fails the service can simply throw an error without roll back. Since the event is not acknowledged the event bus will send the same event again. Now since the service is idempotent, the same database transaction will not happen twice, it will basically overwrite or better(should) skip and directly move to message publishing and acknowledging.

FirebaseFirestore different between OnCompleteListener, OnSuccessListener, OnCanceledListener and OnFailureListener

Can someone explain me how these Listener are different from each other?
AFAIK, If I use OnCompleteListener() I can check if task complete or not and if it complete I can still check that it success or not.
I confuse that when task failed. it happens because task not complete or task not success or it can occurs in both case. And how OnCanceledListener work? When it will be called? and what is the meaning of "Called when the Task is canceled successfully."?
Please explain me, I confuse of these Listener behavior?
A Task is considered complete when the work represented by the Task is finished, regardless of its success or failure. So there may be or may be not an error, but you have to check for that. On the other side, a Task is successful when the work represented by the task is finished, as expected, with no errors.
OnFailureListener is called when a Task fails with an exception. So you can get the message from the Exception to see the reason why your Task failed.
OnCanceledListener is called when the Task is canceled successfully, which means that every Task has a cancel() method and once this method completes successfully, this listener is invoked.
Please also note, if there is a loss of network connectivity (there is no network connection on user device), neither onSuccess() nor onFailure() are triggered. This behavior makes sense, since the Task is only considered completed when the data has been committed (or rejected) on the Firebase servers.

Canceling JavaFX Service when in SCHEDULED state

I am trying to cancel my JavaFX Service using the cancel() method.
Before I call cancel(), I check the Worker state.
System.out.println(service.getState());
System.out.println(service.cancel());
The cancel() method persistently fails when the Worker is in the SCHEDULED state. cancel() returns false, and the Worker proceeds to the RUNNUNG state, before terminating as SUCCEEDED.
I cant find anything in the docs about cancel() not affecting a SCHEDULED Worker. Is this normal behaviour?
If this is the case, then you should file a bug report, as the behavior you describe directly contradicts the specified behavior in the Worker.State javadoc.
A Worker may be cancelled when READY, SCHEDULED, or RUNNING, in which case the final status will be CANCELLED. When a Worker is cancelled in one of these circumstances it will transition immediately to the CANCELLED state.
Could it be some concurrency problem with my Task?
I want somebody to answer questions about potential issues in your code, you need to edit your question to provide an MCVE.
Is there any sources that outlines reasons for why a cancel() would fail?
javafx-src.zip is included in the Oracle Java 8 JRE, you can investigate the source code to determine some of the reasons for it's behavior.

Asynchronous invocation in a ASP.NET application

I'm not talking about asynchronous pages or asynchronous handlers, I just want to know if I should be afraid of any side effect when I invoke an asynchronous method that will end after the page is finished rendering.
Example given: Each time that a user do login, I have to launch a heavy and time consuming SQL operation, but the user doesn't need to know the result of that operation, so I can execute the query using BeginExecuteNonQuery without pass any callback, and finish rendering the page.
My concern is, what happen if the HTTP call ends (because the page is served) and whatever I've executed asynchronously is already running? is ASP.NET or IIS going to cut, destroy, void anything?
Cheers.
That operation will run, even when the request has finished. However, please note that the ASP.NET host aggressively kills threads. When IIS has any reason for unloading or recycling the AppDomain, your background thread will be killed. Unloading happens in several situations. For instance when no new requests have come in for a certain period of time. Or when too many exceptions are fired from the application within a certain period of time. Or when the memory pressure gets too high.
If you need the guarantee, that the operation will finish, I think there are three things you can do:
Speed up the operation so that it can run synchronously, or
Move that that heavy operation to a Windows Service and let that execute it, or
You can hook onto the HostingEnvironment.RegisterObject method (as Phill Haack explains here) (demands full trust) to prevent the AppDomain to go down while that thread is running.
If you have a callback registered, the process will comeback to notify the callback otherwise it will still complete the job. AFAIK - neither ASP.NET or IIS will cut/destroy or void anything as the execution was already ordered and it has to complete.

Resources