Enable to cancel a process until it is finished - bpmn

I would like to ask how it is possible to model a following situation in BPMN:
Users can submit a request, which they can cancel any time until the request is solved. Once the request is solved, it cannot be cancelled. So if the user cancels the request before it is processed, the process ends without further processing. So until there is no result of the request, it can be cancelled.
For example until the research paper is published, it can be discarded by its author.
I model another example of BPMN process, which outlines the problem.
Thanks a lot!

This can be modeled using the boundary message intermediate event (interrupting). The message intermediate event catch the cancel message from user and trigger the stop of the process.

Related

Nsb: Custom behavior after every handler

We want to log every occurrence of a handler running to completion and we're wondering what's the cleanest way to do it.
More specifically, when a Handler completes, we want to write some basic information like the type of the message that was processed etc, to a Db.
One way to do it is by creating and sending a new message (publishing an event) at the end of each handler.
But we're wondering if there is another way to do this without "polluting" the message handlers with those extra line of code :) For example, if after a Handler runs to completion, another method defined elsewhere would pick up execution and handle the logic of writing to the database.
Hope I made myself clear enough. Thanks
You could use the auditing pipeline and forward the audit messages to your audit queue and handle a copy of all messages there...
Here is some more info: https://docs.particular.net/nservicebus/operations/auditing?version=core_7.2
Does that make sense?

How to prevent NServiceBus from not sending messages on errors

I'm new to NServiceBus, so maybe I'm asking something pretty silly here, but is there a way to make NServiceBus not stop sending any messages that are sent in response to a message whose handler fails?
Let me explain with a simple example.
Suppose I have an OrderPaidEvent that has a handler that does the following:
Look for the customer
Start a DB transaction
Update the customer to a good customer
Send an CustomerUpgradedToGoodCustomerEvent message
Commit the DB transaction
Fairly straightforward, all is well in the world. Now a few months later someone else figures that an email would be nice when an order is paid and thus adds another handler to the OrderPaidEvent to send an email.
Unfortunately, now whenever the mailserver has an issue, this second handler will fail with an error which will however prevent the original CustomerUpgradedToGoodCustomerEvent message from being sent (step 4). But because the DB transaction was already committed (step 5) the customer has already been upgraded to a good customer in the database.
This means that even if the OrderPaidEvent handler is retried the customer no longer changes and thus the CustomerUpgradedToGoodCustomerEvent message is never sent. Worse yet, this is all because of a change to the code that has nothing to do with the original message handler and will thus be difficult to detect.
This seems like a massive flaw and since I'm new to this I'm certain there's something I'm doing wrong, but I can't seem to figure out what it is.
Any help from you fine people would be great.
Thanks in advance.
How about breaking down your procedural code into separate handlers?
Thereafter each logical operation will either be done or will not be done based on successful completion of each granular task.
If you add a Saga to the mix then you can make business decisions based on the completed steps in your Saga.
Also maybe read more about transactions and NServiceBus here
First of all I would send out the CustomerUpgradedToGoodCustomerEvent after the commit. At that point you are sure that the event actually took place.
And in response to your question: You could handle the email in some 'SendEmail' command that is raised after the db commit and before the event is published. If that command fails it will not hurt the handling of the OrderPaid event. When mail is up again, the command can be retried and handled normally.

Using Sagas with Recoverabilty

We are having an issue with recovery for messages originating from Sagas.
When a Saga sends a message for processing, the message handler can sometimes fail with an exception. We currently use a try/catch and when an exception is thrown, we "Reply" with a failed message to the Saga. The issue with this approach is that Recoverability retries don't happen since we are handling the error in the message handler.
My thought was to add custom logic to the pipeline and if the Command message implements some special Interface, the custom logic would send a failed message response to the Saga if an exception occurs (after the retries fails), but I'm not sure where to plug into the pipeline that would allow me to send messages after retries fails.
Is this a valid approach? If not, how can I solve for Saga to Handler failure messages after retries?
You can use immediate dispatch to not wait for a handler to complete.
However, I would like to suggest an alternate approach. Why not create a Timeout in the saga? If the reply from the processing-handler isn't received within a certain TimeSpan, you take an alternate path. The processing-handler gets 5 minutes and if it doesn't respond within 5 minutes, we do something else. If it still responds after 6 minutes, we know we've already taken the alternate path (use a boolean flag or so and store that inside the saga data) and put aside the reply that arrived too late.
If you want to start a discussion based on this, check our community platform.

Camunda: how to model task that can be cancelled?

I want to model a process that can be initiated by receipt of a message (which will be done via a REST call). The process will lead to a task that is assigned to a user. The user will supply some extra information and then the process will terminate.
However, I also want to model the case when additional information is received after the first info has been received. Receipt of this extra information via REST should terminate the process.
This overall model represents a computer system that monitors a flow of information and if it detects a problem it creates a task for someone to investigate. However if further information becomes available, the the task should've terminated.
What is the best way of modelling this in BPMN and Camunda please?
What I have at the moment:
(MSE) --> (UT) -->(TEE)
(RT) --> (TEE)
Where:
MSE = Message Send Event
UT = User Task
TEE = Termination End Event
RT = Receive Task
I can successfully start/add a process for using curl to post a message representing the start message. This adds a process and the task is allocated to a user.
However, I don't seem to be able to get the receive task to correlate with the process, it just seems to add a new process. The cancel message that the receive task is supposed to represent should specifically cancel the particular process that it exists in, not any old process.
There are different ways to model this.
You could use an interrupting boundary message receive event and if the extra info was received the user task is canceled by the boundary event.
Another approach would be to use an interrupting event sub process.
If the message with the extra information was received the event sub process is triggered and will cancel the process.
You could also use a parallel gateway and a terminate end event.
But I would recommend one of the methods above-mentioned.

Best way to tell if NServiceBus is still processing?

I am looking for a way to tell if NSB is still processing a message, including any internally triggered events/commands, so that within automated tests I can wait until a process has completed before moving on to the next step.
What is the best way to do this?
As long as you have auditing turned on, check to see when the message you sent the endpoint-under-test appears in the audit queue. When the message is in the audit queue, you can know that it has been successfully processed by the endpoint.