I have several parts of my application, that need to react to events triggered from somewhere else, so the first thing I thought about would be an event bus. These are the requirements I see:
The subscriber method should be typesafe
Implementing an interface (like Subscriber<T>) is not a problem
A subscriber should also receive any events of subtypes to the class it's registered to
Subscribers should be able to be registered with a priority (a simple int) or a default priority hardcoded somewhere in the code. When posting an event, the subscribers will be called in order. The events are mutable and some of their fields will change between subscribers
Each thread will have its own event bus and I will manually register all subscribers, so there's no need for static access
While receiving an event, it should be possible for a subscriber to unsubscribe without raising a ConcurrentModificationException
Bonus requirements I might need down the line:
Register new subscribers while handling events
Send events while receiving one. Those will be processed synchronously before proceeding with the current task
The option to "pool" events that currently have no subscriber and manually process them later (maybe by passing a Consumer).
Guava Eventbus probably does most of those things except for the priority. I can create a simple prioritized subscriber queue by using a TreeSet, but I'm not sure how to integrate it into Guava and I don't know if I want to depend on the whole library just for the bus.
Also, I might need a CopyOnWriteArrayList for the concurrent stuff (adding/removing while iterating), but I don't know about the performance implications. On that note, there probably won't be more than 10-15 subscribers at a time.
Normal events are not designed to be mutable. You should stick with immutable data. Also subscribers are not intendet to be called within a certain order or to interact with another.
For your usecase you could build different event busses for each priority. A subscriber could handover a copy of the modified event to the next priority bus.
Related
I've got a spring app that uses multiple queues to handle event processing. The app adds messages to these queues when specific events occur. When the messages are consumed they are removed implicitly. Example : RETRY_QUEUE to reprocess the message SUCCESS_QUEUE if the message gets through processing.
Internally I use #JmsListner to monitor the queue for incoming messages, how do I create a custom event handler that can be used to publish events when messages are added or removed from these queues ? I wanted to monitor these queues using prometheus gauges by inc() or dec() the queue size based on enqueue or dequeue events.
You can use Spring AOP principles to create point cuts to the JmsListener.onMessage() and JmsTemplate.send(..) methods to publish events. This approach will decouple your business logic with your event publish logic.
See also : #After, #Before, #AfterReturning, etc advices.
https://docs.spring.io/spring-framework/docs/2.5.6/reference/aop.html
I am playing a bit with Reactor right now. While trying to build a small demo game (just to get accustomed to the framework), I need the ability to have multiple "entities" subscribed to a publisher. But I also need each published event to reach exactly one subscriber. For now, they all always get it. I know that I could build some "latch" into this event so that all but one subscriber discard it.
But I think in the sea of features, there might be an operator or something that already does exactly this...
Multiple subscribers to a single publisher. Each subscriber would need to apply a different filter too though.
Each event from the publisher going only to a single subscriber in no particular order... (The filter does not guarantee uniqueness, there could be multiple subscribers using the same filter).
Randomness is cool but not required (since the subscriber will unsubscribe upon receiving this event). You might have guessed that this will be the kill signal for the entity ;).
Thanks!
Looks like UnicastProcessor does the trick.
I would like to #Subscribe a method in a Runnable that is created by a ScheduledFuture, so that I can signal it from another thread whether to run. Because a ScheduledFuture creates the object at some future time, there is no scope for the #Subscribe listener to pick up my event. So, I'm wondering how long an event sits in the bus, waiting to picked up by a listener? Is the actual pub-sub synchronous wrt sending/receiving events or will they sit in a queue for some duration before timing out?
Thanks.
Guava's EventBus does not provide sticky events. Additionally, due to the design of EventBus, it's not as straightforward as it could be to extend it to implement such a sticky design, as a lot of the internals are package-private (e.g. the logic to discover which methods on a registered object are annotated with Subscribe and mapping them to the proper event type).
I do think there are some other libraries out there which do provide this, like GreenRobot's event bus (https://github.com/greenrobot/EventBus), but without introducing a new library you'll have to build it more or less from scratch.
An alternative that I've used is RxJava's Observables with a replay(1) operator, so that subscribing to the observable will always immediately invoke the subscription callback with the last item, but it's not a drop-in replacement.
Suggestions on patterns for handling the following scenario:
A single thread that dispatches events to consumers. There is a 1:1 between each event and a consumer (each event is dispatched to a single consumer based on event/consumer id match).
Consumers process events at varying speeds and can consume events in configurable batch sizes (e.g. a consumer could consume 20 events at a time).
The producer thread should always be able to dispatch events to consumers that are capable of consuming. Each consumer maintains a queue of events it has consumed (possibly in batch) and processes these on its own thread, so the hand-off from producer to consumer is asynchronous.
If no consumers can consume at any point in time, what should happen to the dispatch thread?
yield() it
wait() & force consumers to call notify() on it
sleep() for a fixed time period
spin
Any reason to prefer one over the other?
Some pros & cons:
yield is simple
forcing consumers to call notify adds complexity
sleep for a fixed time would suit for non time sensitive requirements
spinning eats up a CPU, unnecessary unless we need as fast as possible event delivery
Any other considerations?
Another way you should consider would be writing it to a BlockingQueue. Let the queue manage requests sent without listeners.
Even better: write a Broker that owns a BlockingQueue and maintains a List of Consumers. Have the Broker notify the List of Consumers when a Producer sends a new Event.
I'd use the PropertyChangeListener and EventObject built into Java Beans since JDK 1.0 to do this in memory.
a) You could choose yield but depending on how good the environment is, this could essentially become a no-op. So this would essentially have the same result as spinning.
b) Sleep is an easy choice but then you should come up with how long to sleep. Doing sleep(0) also will not help as it will be same as doing (a)
The force of notification is more complicated but you have complete control of your flow.
Take a look at JMS. JMS is designed to handle exactly this kind of use case.
A full scale JMS installation might be overkill in your scenario – you don't provide enough information.
I am using protobuf for implementing a communication protocol between a Java application and a native application written in C++. The messages are event driven: when an event occurs in the C++ application a protobuf message is conructed and sent.
message MyInterProcessMessage {
int32 id = 1;
message EventA { ... }
message EventB { ... }
...
}
In Java I receive on my socket an object of the class: MyInterProcessMessageProto. From this I can get my data very easily since they are encapsulated into each other: myMessage.getEventA().getName();
I am facing two problems:
How to delegate the processing of the received messages?
Because, analysising the whole message and distinguishing the different event types and the actions they imply resulted in a huge and not maintainable method with many if-cases.
I would like to find a pattern, where I can preserve the messages and not only apply them, but also undo them, like the Command pattern is used to implement this.
My first approach would be: create different wrapper classes for each event with a specified apply() and undo() method and delegate the job this way.
However I am not sure if this is the right way or whether there are not any better solutions.
To clarify my application:
The Java application models a running Java Virtual Machine and holds information, for instance Threads, Monitors, Memory, etc.
Every event changes the current state of the modeled JVM. For instance, a new thread was launched, another thread goes into blocking state, memory was freed etc. In the same meaning the events are modeled: ThreadEvent, MemoryEvent, etc.
This means, the messages have to be processed sequentially. In order to iterate back to previous states of the JVM, I would like to implement this undo functionality.
For undo I already tried. clearAllStates, apply Events until Event #i.
Unfortunately with 20.000+ events this is total inefficient.
To provide a tailored answer it would be good to know what you're doing with received messages, if they can be processed concurrently or not, and how an undo impacts the processing of messages received after and undo'ed message.
However, here's a generic suggestion: A typical approach is to delegate received messages to a queue-like handler class, which usually runs in an own thread (to let the message receiver get ready for the next incoming message as soon as possible) and sequentially processes received messages. You could use a stack-like class to keep track of processed messages for the sake of the undo feature. You could also use specific queues and stacks for different event types.
Basically this resembles the thread pool pattern.