Is there a way to control the order in which commands that are registered in a CompositeCommand get called? Do they get call and executed in a sequential order?
Looking at the code, registered commands execute one after another, in the order of registration. There's no test for this in the fixture, though, so I wouldn't rely too heavily on this behavior.
Related
I am attempting to accomplish something along these lines with Quarkus, and Naryana:
client calls service to start a process that takes a while: /lra/start
This call sets off an LRA, and returns an LRA id used to track the status of the action
client can keep polling some endpoint to determine status
service eventually finishes and marks the action done through the coordinator
client sees that the action has completed, is given the result or makes another request to get that result
Is this a valid use case? Am I visualizing the correct way this tool can work? Based on how the linked guide reads, it seems that the endpoints are more of a passthrough to the coordinator, notifying it that we start and end an LRA. Is there a more programmatic way to interact with the coordinator?
Yes, it might be a valid use case, but in every case please read the MicroProfile LRA specification - https://github.com/eclipse/microprofile-lra.
The idea you describe is more or less one LRA participant executing in a new LRA and polling the status of this execution. This is not totally what the LRA is intended for, but surely can be used this way.
The main idea of LRA is the composition of distributed transactions based on the saga pattern. Basically, the point is to coordinate multiple services to achieve consistent results with an eventual consistency guarantee. So you see that the main benefit arises when you can propagate LRA through different services that either all complete their actions or all of their compensation callbacks will be called in case of failures (and, of course, only for the services that executed their actions in the first place). Here is also an example with the LRA propagation https://github.com/xstefank/quarkus-lra-trip-example.
EDIT: Sorry, I forgot to add the programmatic API that allows same interactions as annotations - https://github.com/jbosstm/narayana/blob/master/rts/lra/client/src/main/java/io/narayana/lra/client/NarayanaLRAClient.java. However, note that is not in the specification and is only specific to Narayana.
Lets assume I have defined the routing slip activity. Within Execute method I would like to make several asynchronous service calls. Lets assume 3 service calls. Two of them succeed and one fails. Then I would like to execute compensate action of this activity in order to compensate the changes introduced by two succeeded service calls. From what I see the compensation only runs for previous activities, the current activity compensation has no chance to be invoked when there is exception somewhere in it. Is there a way to deal with it or I should change the approach?
I would like to achive sth similar to
using MassTransit.
You should have three separate activities, and execute them in order, so that as they succeed individually, they are added to the log. If an activity fails, the previous activities will be compensated.
By having all three calls in a single activity, you're going against the entire reason for having the routing slip and activities.
I am building a model simulating an order process tiggering a production flow. The production flow should be initiated once the order is placed. My idea is to use an event named "start production" that is monitoring a boolean, which is changed by the above order entity.
I am facing various issues:
When starting the simulation my startProduction variable is changing from its initial value false to true already applying the starting condition in the event
If I apply in the action of the event the command event.restart() the simulation crashes as anylogic is constantly re-checking the event condition
How can I either solve the above problems or simulate the start of production based on an order income with a conditional logic?
Since my comment was the answer, let me add the answer here too.
It is always possible to use an event to trigger actions in your model, but it's also the most ineffective way, because you constantly running code that you may not need, making your simulation slower. The best thing you can do, whenever possible is to trigger things in the actions of your blocks. In this case when the order is generated you can use the inject function to add an agent to your production flow.
On the other hand, you can only use the restart function if the mode of your event is "user control" and it's probably the reason why you were getting an error.
Could you please tell me why sales_order_save_commit_after is triggered twice when order is completed?
I moved all logic to sales_order_save_before, but I use sales_order_save_commit_after to make sure that it's called only once. I want to make sure that there are no superflous writing to database. I tried to use debugger to understand how it works, but I haven't understood so far, it seems rather complicated.
I see 2 callbacks but I can't understand why is there 2 callbacks for model order.
Does magento write to database several times that triggers sales_order_save_commit_after multiple times?
If an order contains configurable products, the collection returned by $order->getAllItems(); will contain parent and child products resulting in double element count for this product type. It is safer to use $order->getAllVisibleItems()
I'm trying to follow TDD (i'm newbee) during development of Service class which builds tasks passed by Service clients. The built objects are then passed to other systems. In other words this service takes tasks but returns nothing as a result - it passes built tasks to other Services.
So I'm wondering how can I write test for it because there is nothing to assert.
I'm thinking about using mocks to track interactions inside the service but I'm a little bit afraid of using mocks because I will be tied up with internal implementarion of the service.
Thanks all of you in advance!
There's no problem using mocks for this, since you are effectively going to be mocking the external interface of the components that are used internally in the component. This is really what mocking is intended for, and sound like a perfect match for your use case.
When doing TDD it should also allow you to get those quick turnaround cycles that are considered good practice, since you can just create mocks of those external services. These mocks will easily allow you to write another failing test.
You can consider breaking it up in a couple classes. One responsible to build the list of tasks that will be executed, and the other responsible to execute the list of tasks it is handed. This way you can directly test the code that build the lists of tasks.
That said, I want to add a sample I posted on another question, regarding how I view the TDD process when external systems are involved.
Lets say you have to check whether
some given logic sends an email, logs
the info on a file, saves data on the
database, and calls a web service (not
all at once I know, but you start
adding tests for each of those). On
each test you don't want to hit the
external systems, what you really want
to test is if the logic will make the
calls to those systems that you are
expecting it to do. So when you write
a test that checks that an email is
sent when you create an user, what you
test is if the logic calls the
dependency that does that. Notice that
you can write these tests and the
related logic, without actually having
to implement the code that sends the
email (and then having to access the
external system to know what was sent
...). This will help you focus on the
task at hand and help you get a
decoupled system. It will also make it
simple to test what is being sent to
those systems.
Not sure what language you're using so in psuedo-code it could be something like this:
when_service_is_passed_tasks
before_each_test
mockClients = CreateMocks of 3 TaskClients
tasks = GetThreeTasks()
myService = new TaskRouter(mockClients)
sends_all_to_the_appropriate_clients
tasks = GetThreeTasks()
myService.RouteTaks(tasks)
Assert mockClients[0].AcceptTask(tasks[0]) was called
Assert mockClients[1].AcceptTask(tasks[1]) was called
Assert mockClients[2].AcceptTask(tasks[2]) was called
if_one_routing_fails_all_fail
tasks = GetTasksWhereOneIsFailing()
myService.RouteTaks(tasks)
Assert mockClients[0].AcceptTask(*) was not called
Assert mockClients[1].AcceptTask(*) was not called
Assert mockClients[2].AcceptTask(*) was not called