Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - event processing design

I am trying to develop a system which will be based on processing certain events and generating data. Each event will contain (possibly) several different fields and each listener will process some or them. I have the following two approaches in mind

  1. Within the event generation class, I will register multiple event listeners, each listening for one particular value of a specific field of the event, for instance:

    public class MicroListener implements Listener {
    
    public void processEvent(Event e){
        if(e.getName().equals(registeredName)) { ... }
    }
    

This is tempting, as processing is done within the object itself, and there is no centralised processing of events, rather allowing each object to process the information. The disadvantage, possibly fatal, is the fact that each event (out of a couple of hundred thousand) will have to be broadcast to all listeners, while only tiny fraction will actually do sth with it. It will probably generate a great performance hit in the long run...

  1. A centralised listener, which will listen and act upon all events, and delegate processing to the corresponding event processors, for instance:

     public class CentralListener implements Listener {
    
        Map<String, Processor> processorsByName;
    
        public void processEvent(Event e){
            processorsByName.get(e.getName()).process(e);
        }
    }
    

This would be faster, but it would require separate maps or collections of processors for any other part of the event e.g. processor that checks event ID etc. This is not the case in approach 1. as we would simply generate another set of listeners and register them with the event generation class.

What do you guys think about any of these? Do they make sense or would you rather advise for sth totally different?

like image 717
Bober02 Avatar asked Oct 06 '22 23:10

Bober02


1 Answers

This is a common design decision, and I don't think there is a generic answer that is correct for all (or even most) cases. I could list the various trade-offs in either approach, but they are probably obvious. At a high level I would favor whatever design best fits the conceptual model (and doesn't create a mess of extraneous classes) before I would consider the possible performance implications.

If performance was of utmost concern, then a centralized controller using a large switch/case block switching on integer event ids would probably be fastest. ...and also the least flexible/maintainable over time.

You might want to review the Guava project's EventBus. It uses annotations to register event listeners and provides a very clean api for this type of event broadcasting/subscribing. The event subscribers are notified according to the type of event they declare in their method signature. It's quite slick and saves a lot of boilerplate. I don't know how well it would scale to thousands of event types, but unlike some similar libraries, the event bus is not global. You can create different event bus instances to separate event processing when it makes sense to do so.

like image 144
kaliatech Avatar answered Oct 10 '22 02:10

kaliatech