Is it good idea call third party services from axon aggregate - spring

I have an axon aggregate. It handle command and before applying event has to invoke third party service for validation some parameters, according to this validation i apply events or not. Is it good practice? Or I have make validation before i send command?
#Aggregate
public class SomeAggregate {
[...]
#CommandHandler
public void someHandler() {
if(thirdPartyService.invoke) {
apply(...)
}
}
}

If it's a non-blocking (domain) service, something like a finite state machine, it's okay to call from within the aggregate, since it's most likely going to finish soon.
However, 'third party service' to me sounds like an outbound call, which might take some time.
When Axon loads an aggregate, it blocks the aggregate so no other thread can change it's state/handle commands on it.
A third-party service would mean that the aggregate is blocked even longer.
Hence, I would suggest not calling a third party service in your aggregate.
Either call the service prior to entering the aggregate or perform a compensating action after command handling was finalized to revert the decision. Which of the two makes most sense in your scenario, is dependent on your domain. I see "pre-validation" through the third-party service however as the most reasonable option to take.

It depends. If your third party service has side effects and isn't idempotent then I'm not sure what to do (I'm still trying to figure it out).
If it does have side effects, then I would want the aggregate to block / lock and use the aggregate's state / history to carefully manage such an interaction like this
#Aggregate
public class SomeAggregate {
[...]
#CommandHandler
public void someHandler() {
/*
Reason about whether its appropriate to send a request.
e.g. if a request has been sent but no response has been received,
then depending on the third party service it might be in an indeterminate state.
Instead of trying to interact with it, it might be better
to notify someone instead.
*/
rejectIfNotSafe()
/*
Effectively locks this interaction / any other instances in the same path
should get a concurrent modification exception when trying to commit this event.
*/
commit(new ThirdPartyServiceRequested())
if(thirdPartyService.invoke) {
apply(...)
}
}
}
But Axon's 'unit of work' means that the emitted events won't be published / committed until the command handler has completed, so we can't guard is this manner.
Any ideas?

Related

Axon Event only picked up by one instance of my service instead of all (fan-out)

We have a Spring micro-service connected to Axon with an #Component and an #EventHandler function on this class. Like this:
#Component
#AllowReplay(false)
class AClass {
#EventHandler
fun on(someEvent: SomeEvent) {
...some handling here
}
}
The Event gets picked up normally and everything works fine but when we run multiple instances of our service only one instance of the service picks up the event. I userstand that this has to do with the way the event processors work (https://docs.axoniq.io/reference-guide/axon-framework/events/event-processors) but I need all instances of the service to pick up the event. How can I configure this?
It pretty much depends on how you are configuring and using it.
So, 'pick up' events, the way you describe, I assume that are events being handled.
In that case, and another assumption here that you are using some sort of Tracking Event Processor (TEP), this is where this logic and responsability is.
In essence, a TEP is responsible for 'tracking' which events it already received to not double react on those.
In your scenario, seems like your apps/instances are sharing the same database (hence sharing the same tokens) and that's why you see it.
About your 'workaround', you are just assigning names to a Processing Group (which can also be done using annotations like this: #ProcessingGroup("processing-group-name-you-want"). If you do not assign a name, the package is the default name used.
Every Processing Groups has a tracking token behind it. In this case, you get multiple tokens and 'react' to the same event multiple times.
For more info about Processing Groups, I recommend this answer.
The answer that works for me, although not the prettiest: Axon 'merges' processors based on package name so multiple instances of a service result in a single processor.
By using unique processing groups you can trick Axon into not 'merging' the different processors into one.
#Autowired
fun configure(configurer: EventProcessingConfigurer) {
configurer.assignProcessingGroup { t: String? -> "${t}_${UUID.randomUUID()}" }
}

Is there a hook for reacting to a catching up Axon projection?

I want to implement a Axon projection providing a subscription query. The projection persists entities of a specific based on the events (CRUD). The following should happen if a replay of the projection is executed:
Inform about a empty collection via the subscription query.
Process the events until the projection catches up with the event store.
Inform about the current state of the entities via the subscription query.
My intention is that the subscription query should not inform about many events in a very short time and I want to prevent informing about many intermediate positions (e.g. create and delete a specific entity, it should not be used in the subscription query, because it is not available after catching up).
Currently I cannot implement the third step, because I miss a hook for reacting to the moment when the Axon projection is catching up again.
I use Axon v4.5 and Spring Boot v2.4.5.
At the moment, the Reference Guide is sadly not extremely specific on how to achieve this. I can assure you though that work is underway to improve the entire Event Processor section, including a clearer explanation of the Replay process and the hooks you have.
However, the possible hooks are stated as it is (you can find them here).
What you can do to know whether your event handlers are replaying yes/no, is to utilize the ReplayStatus enumeration. This enum can be used as an additional parameter to your #EventHandler annotated method, holding just two states:
REPLAY
REGULAR
This enumeration allows for conditional logic within an event handler on what to do during replays. If an event handler for example not only updates a projection but also sends an email, you'd want to make sure the email isn't sent again when replaying.
To further clarify how to use this, consider the following snippet:
#EventHandler
public void on(SomeEvent event, ReplayStatus replayStatus) {
if (replayStatus == REGULAR) {
// perform tasks that only may happen when the processor is not replaying
}
// perform tasks that can happen during regular processing and replaying
}
It's within the if-block where you could invoke the QueryUpdateEmitter, to only emit updates when the event handler is performing the regular event handling process.

Am I right in separating integration events from domain events?

I use event sourcing to store my object.
Changes are captured via domain events, holding only the minimal information required, e.g.
GroupRenamedDomainEvent
{
string Name;
}
GroupMemberAddedDomainEvent
{
int MemberId;
string Name;
}
However elsewhere in my application I want to be notified if a Group is updated in general. I don’t want to have to accumulate or respond to a bunch of more granular and less helpful domain events.
My ideal event to subscribe to is:
GroupUpdatedIntegrationEvent
{
int Id;
string Name;
List<Member> Members;
}
So what I have done is the following:
Update group aggregate.
Save down generated domain events.
Use these generated domain events to to see whether to trigger my integration event.
For the example above, this might look like:
var groupAggregate = _groupAggregateRepo.Load(id);
groupAggregate.Rename(“Test”);
groupAggregate.AddMember(1, “John”);
_groupAggregateRepo.Save(groupAggregate);
var domainEvents = groupAggregate.GetEvents();
if (domainEvents.Any())
{
_integrationEventPublisher.Publish(
new GroupUpdatedIntegrationEvent
{
Id = groupAggregateId,
Name = groupAggregate.Name,
Members = groupAggregate.Members
});
}
This means my integration events used throughout the application are not coupled to what data is used in my event sourcing domain events.
Is this a sensible idea? Has anyone got a better alternative? Am I misunderstanding these terms?
Of course you're free to create and publish as many events as you want, but I don't see (m)any benefits there.
You still have coupling: You just shifted the coupling from one Event to another. Here it really depends how many Event Consumers you've got. And if everything is running in-memory or stored in a DB. And if your Consumers need some kind of Replay mechanism.
Your integration Events can grow over time and use much bandwidth: If your Group contains 1000 Members and you add 5 new Members, you'll trigger 5 integration events that always contain all members, instead of just the small delta. It'll use much more network bandwidth and hard drive space (if persisted).
You're coupling your Integration Event to your Domain Model. I think this is not good at all. You won't be able to simply change the Member class in the future, because all Event Consumers depend on it. A solution could be to instead use a separate MemberDTO class for the Integration Event and write a MemberToMemberDTO converter.
Your Event Consumers can't decide which changes they want to handle, because they always just receive the full blown current state. The information what actually changed is lost.
The only real benefit I see is that you don't have to again write code to apply your Domain Events.
In general it looks a bit like Read Model in CQRS. Maybe that's what you're looking for?
But of course it depends. If your solution fits your application's needs, then it'll be fine to do it that way. Rules are made to show you the right direction, but they're also meant to be broken when they get in your way (and you know what you're doing).

Long running async method vs firing an event upon completion

I have to create a library that communicates with a device via a COM port.
In the one of the functions, I need to issue a command, then wait for several seconds as it performs a test (it varies from 10 to 1000 seconds) and return the result of the test:
One approach is to use async-await pattern:
public async Task<decimal> TaskMeasurementAsync(CancellationToken ctx = default)
{
PerformTheTest();
// Wait till the test is finished
await Task.Delay(_duration, ctx);
return ReadTheResult();
}
The other that comes to mind is to just fire an event upon completion.
The device performs a test and the duration is specified prior to performing it. So in either case I would either have to use Task.Delay() or Thread.Sleep() in order to wait for the completion of the task on the device.
I lean towards async-await as it easy to build in the cancellation and for the lack of a better term, it is self contained, i.e. I don't have to declare an event, create a EventArgs class etc.
Would appreciate any feedback on which approach is better if someone has come across a similar dilemma.
Thank you.
There are several tools available for how to structure your code.
Events are a push model (so is System.Reactive, a.k.a. "LINQ over events"). The idea is that you subscribe to the event, and then your handler is invoked zero or more times.
Tasks are a pull model. The idea is that you start some operation, and the Task will let you know when it completes. One drawback to tasks is that they only represent a single result.
The coming-soon async streams are also a pull model - one that works for multiple results.
In your case, you are starting an operation (the test), waiting for it to complete, and then reading the result. This sounds very much like a pull model would be appropriate here, so I recommend Task<T> over events/Rx.

Axon How can I add an event listener/interceptor to intercept events before they reach their handlers?

I have a projection class (to build a read model) and I want to add an interceptor for its events in a way that if the id passed in the event leads to a null object (non-existent in my db) then I want to block it, otherwise let it pass.
This way I will escape adding a null checker on EVERY event handler.
#EventHandler
public void onEvent(Event event) {
Entity entity = getEntity(event.getId());
if(entity!=null){ // what I don't want to add on every event handler
dostuff();
}
}
I found that axon provides an interface called EventListener but I'm not sure how to work with it and I'm not sure if this will be intercepting ALL of my events or if I will be able to intercept select events.
There is no mention anywhere for this interface but in the official documentation (with no actual examples or so)
You are right on the part the the Reference Guide still needs some improvements #bleh10 - I can assure you, they're being worked on, the team is just spread out relatively thin.
In absence of the sought after example, I think I can give you some guidance.
What you're looking for is a MessageHandlerInterceptor implementation, specifically for the EventMessage type. As the naming suggests, it intercepts messages prior to being handled, which corresponds perfectly with the question you've posed.
Secondly, you obviously need a place to configure these. Within an Axon application, the technical aspect of delivering events to your #EventHandler annotated methods, is the Event Processor. As such, it is in charge of ensuring the Event Messages flowing through it are intercepted as desired.
Hence, the place to configure your EventMessage MessageHandlerInterceptor, is on the EventProcessor implementation you've chosen. To ensure a given Event Handling Component is set in a specific EventProcessor, you can specify it's Processing Group by annotating the class with the #ProcessingGroup annotation.
From there on, you can easily configure specific properties for your Event Processor by utilizing the EventProcessingConfigurer. More specifically, I'd suggest to use the EventProcessingConfigurer#registerHandlerInterceptor(String, Function<Configuration, MessageHandlerInterceptor<? super EventMessage<?>>>) method for this.
The first String parameter is meant to describe the name of your Processing Group. The second is a Function which receive the Axon Configuration and should output a MessageHandlerInterceptor which can deal with the EventMessage class.
Hope this helps you out!

Resources