Is it allowed to loop back from an error event? - BPMN - bpmn

I am modeling a process for a company. This process involves sending a message to a client. Now, this client can either accept, decline, or make a different proposition as a response.
To catch this, I have modeled the process like so:
I'm not sure if this is the correct way of modeling. It seems the most understandable way, though, but since the modeling is part of my bachelor thesis, I have to get this right.
Thanks for your answers/thoughts in advance!
Edit:
Per Drux's feedback, I have changed the model like so:
This model does away with the wrongful error event and makes it so that each outcome has its path. This should be more easy to understand.

Your model looks correct, from a BPM perspective it looks okay, which was your original question. From an "understanding what is going on" perspective it seems a bit off to me.
First of all, reading this it seems like you would have a human activity "Confirms Appointment" immediately after sending the message to the client. Given that the client hasn't responded yet that feels wrong. Secondly you are using a error event for something I would not think of as an error - a user as you say can respond 3 ways, so throwing an error for an expected response feels wrong.
Based on your description above I would model this by waiting at a Message Event right after you send the notice to the Client. This would be "Client Response" and this Intermediate Message Event would then go to a decision gateway that would go to the correct next step based on how the customer responded - "Confirm", "Decline", "Counter Propose". In this way while waiting for the client response there isn't an activity that should not be acted on for the "Aletha" swim lane.

Related

BPMN Intermediate Events Attached to an Activity Boundary

how would you drow diagram - example A or Example B or both are fine? In Example A there is an event, one extra task and process is back in the main flow. Example B - if the event occurs process is not back in main flow. Is it correct to draw process like in example A? Examples enclosed. Thank you in advance for help.
I draw examples (enclosed) and checked in BPMN specification but still have doubs.
I would go a step further and put a gateway in front of "Application Analysis" and then draw the arrow from the message event to that gateway (so the gateway is only used to join, doesn't need a condition, it is best practice, you could draw the arrow from the message event directly back on the task itself and it would express the same thing).
The basic reasoning is that you shouldn't have multiple tasks for the same thing in the diagram unless it is really at a different stage in the workflow.
However it isn't exactly the same as your workflow, because like this the customer could change the loan amount multiple times and not just once.
There are some problems:
I think you want to make the message event interrupting, otherwise you grant both loans, the original one and the changed one.
After "Application Analysis" there should probably be a gateway that checks the result of the analysis and only if it was ok you grant the loan.

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.

Pause a sub-process BPMN

I've recently started at a new business and some of the processes are becoming a bit of a challenge to map out. Quite frequently we have a process that needs to go "on hold" when an event, which can occur at any point, is triggered. The problem I'm having mapping this out correctly is how to "restart" the process from where it left off, since it can effectively pause/unpause at any point.
Here's what I currently have:
Process Example
Basically, I need to have "Something Happened 2" not fully interrupt the sub-process, it just needs to put it on "hold". The actual situation is essentially that a customer can make a complaint while we handle their overdue bill, so we put the process on hold wherever it was at until we resolve the complaint, and then restart the process.
I'm not entirely sure the best approach to documenting this and couldn't find anything clear in the documentation, since a non-interupting event seems to have the rest of the process still continue forward in parallel.
Any help would be majorly appreciated.
If you really want to restart the whole sub-process from the beginning, then you could frontload an exclusive gateway. Once the complaint is dealt with, you can direct the sequence flow to that gateway, which would restart the sub-process. See below for an example (I have simplified your diagram a bit).

Is there a way to tell NServiceBus to not retry a message?

The "retry" system with NServiceBus is great. It works fantastic in making sure small things like dead locks don't mess us up.
However, sometimes I KNOW that a message is bad. Bad in the sense that no amount of retries is going to help.
Is there a way to tell NServiceBus: "This message is a bad apple, move it to the error queue"? (And have it skip the retries?)
If you are using NSB 3, you can take a look at the IManageMessageFailures interface. This will allow you to plug in your functionality, but this is after the message has failed. If you would like to get at the message earlier, then take a look at the Message Mutators feature. This gets you in both at the transport layer and at the application layer.
Would calling Bus.DoNotContinueDispatchingCurrentMessageToHandlers(); inside the handler not be a simpler way of doing this?

NServicebus time-sensitive auction implementation

We are using NServicebus to design a system that has to solve an auction scenario: we want to send out a message to a set of companies that can bid on an item. After we've received all the bids we want to send the item to the highest bidder.
We initially thought this kind of scenario was perfectly suited for NServicebus: Pub/sub for sending out a message (e.g. BidOnItem or ItemAvailable), message handlers that subscribe to that message for each interested company and a saga for storing the different bids we receive and we're done.
In a normal auction we could set a timeout at say 5 minutes and then decide who gets the item based on the highest price we've received. We don't have that luxury. The problem that we've run in to is that our specific scenario has a tricky, non-negotiable business requirement: the auction is very time-sensitive. Seconds matter. What we'd like to do is decide who gets the item as soon as all companies have responded. Usually this will happen in a matter of seconds. We want to decide the second all subscribers have responded. Obviously we'll also still implement a timeout but that will be the exception rather than the rule. If we want to determine if everyone has replied we'd need something like a list of all the handlers at all the endpoints that are subscribed to the BidOnItem message. It appears the NServicebus API doesn't provide this information.
There are some future requirements we have to implement as well centered around data enrichment and approval/rejection decisions that would benefit greatly from knowing whether all handlers on a pub/sub channel have responded. I know this reeks of request/reply which is something NServicebus discourages because of the coupling it causes but this requirement feels like something that's fundamental for a lot of processes that is very hard to implement outside of the core bus infrastructure. In that sense it feels a lot like Saga.ReplyToOriginator which NServicebus does provide.
What would be the "NServicebus Way" to solve this problem?
Pub/Sub is usually not the way to go in these auction scenarios. What if your saga would do reguest/response with your bidders?
S: OnAuctionCreated (carries the list of bidders, or you could fetch them somewhere)
foreach bidder in event.Bidders
-bus.Send(RequestBidFrom(bidder))
SetTimeout(X)
S: OnBidResponse
bids.Add(response.Bidder,response.Bid)
if(bids.Count()== Data.TotalBidders)
CompleteAuction();
S:OnTimeout
CompleteAuction()