Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lock on handler (or Listener) #152

Closed
ndr-brt opened this issue Jun 26, 2017 · 7 comments
Closed

Lock on handler (or Listener) #152

ndr-brt opened this issue Jun 26, 2017 · 7 comments

Comments

@ndr-brt
Copy link

ndr-brt commented Jun 26, 2017

Hi, how can I lock a single handler (or entire listener) to avoid concurrent event handling in asyncronous mode?

@ndr-brt
Copy link
Author

ndr-brt commented Jun 26, 2017

Ok, I handle lock on single Listener with the "Synchronized" annotation, but there's a way to obtain lock on the entire listener?

@bennidi
Copy link
Owner

bennidi commented Jun 26, 2017 via email

@ndr-brt
Copy link
Author

ndr-brt commented Jun 27, 2017

You think this could be a future feature?
It will be intersting for my case...

In this example, I need that when I launch two events in this order:
EntityCreatedEvent
EntityUpdatedEvent

The listener will wait the handle of the EntityCreatedEvent before handling the EntityUpdatedEvent.

public class Listener {
    private Repository repository;

    @Handler
    public void consume(EntityCreatedEvent event) {
        repository.insert(readModelFrom(event));
    }

    @Handler
    public void consume(EntityUpdatedEvent event) {
        ReadModel model = repository.get(event.getId());
        model.updateWith(event);
        repository.update(model);
    }
}

@techyourchance
Copy link

techyourchance commented Jun 27, 2017

How about this:

public class Listener {

    private final Object LOCK = new Object();
    private Repository repository;

    @Handler
    public void consume(EntityCreatedEvent event) {
        synchronized(LOCK) {
             repository.insert(readModelFrom(event));
        }
    }

    @Handler
    public void consume(EntityUpdatedEvent event) {
        synchronized(LOCK) {
            ReadModel model = repository.get(event.getId());
            model.updateWith(event);
            repository.update(model);
        }
    }
}

This is the simplest approach that will synchronize everything. If you want to perform synchronization only if events come in a specific order you can use something like Semaphore.

@bennidi
Copy link
Owner

bennidi commented Jun 27, 2017 via email

@ndr-brt
Copy link
Author

ndr-brt commented Jul 3, 2017

@bennidi yeah, the second solution will the best in this case, but there could be a failing scenario:

EntityCreatedEvent -> takes some time to be fully consumed
EntityUpdatedEvent n1 -> try to get, but there's no read model, so i put it in queue
(meanwhile read model is created)
EntityUpdatedEvent n2 -> gets consumed, before the n1

I think that this problem could be handled by mbassador, giving opportunity to serialize all the events in a single listener. One futhcer enanchement could be to serialize them by a value like uuid or entity id (present in the event).

@bennidi
Copy link
Owner

bennidi commented Jul 4, 2017 via email

@bennidi bennidi closed this as completed Aug 27, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants