moleculer
                                
                                 moleculer copied to clipboard
                                
                                    moleculer copied to clipboard
                            
                            
                            
                        Proposal: allow event subscriber to determine whether it is balanced
Is your feature request related to a problem? Please describe.
Letting an event publisher determine whether an event is balanced or not (emit vs broadcast) creates tightly coupled services and can cause issues among subscribers.
For example, imagine a user service publishes a user.created event. An activity service maintains a local cache of recently active users and subscribes to user.created so every instance can update its cache. An email service also subscribes to user.created because it wants a single instance to send a welcome email to the new user.
In this example, should the user service emit or broadcast the user.created event? I believe it shouldn't have to decide, because making that decision requires the publisher to know about the subscribers and the logic of their event handlers. Instead, I think each subscription should determine whether or not it needs to be balanced.
Describe the solution you'd like
I propose that a balanced: boolean property be added to the event definition to determine what kind of subscription should be created. Additionally, the emit and broadcast methods should be unified into a single method, though there are likely other ways to implement this proposal that avoid breaking changes.
// activity.service.js
module.exports = {
  name: 'activity',
  events: {
    'user.created': {
      balanced: false,
      handler(ctx) {
        // Update local user cache
      }
    }
  }
};
// email.service.js
module.exports = {
  name: 'email',
  events: {
    // Should `balanced: true` be the default?
    'user.created'(ctx) {
      // Send welcome email
    }
  }
};
Describe alternatives you've considered
Examples like the above can be solved by publishing multiple events to different groups — emit to the email group and broadcast to the activity group — to satisfy the different subscribers. However, this doesn't solve the philosophical issue that publishers and subscribers are tightly coupled.
Additional context
Inspired by research on (and possibly a solution for) #791
Could similar functionality be achieved through naming events in a way that reflects whether they are balanced or not and then firing off both events when a user is created? If the above was implemented it would likely have to do something similar (do both a emit and broadcast for all events behind the scenes or be tightly coupled to its subscribers to know which event types it needs to send based on the subscribers configuration). Seems like it would solve for the coupling of needing to know about your subscribers when publishing an event. The downside I see to this approach is potentially performance and code-cleanliness.
Something like:
broker.emit("user.created.emit", user);
broker.broadcast("user.created.broadcast", user);
And then to subscribe:
// activity.service.js - { balanced: false }
module.exports = {
  name: 'activity',
  events: {
    'user.created.broadcast': {
      handler(ctx) {
        // Update local user cache
      }
    }
  }
};
// email.service.js - { balanced: true }
module.exports = {
  name: 'email',
  events: {
    'user.created.emit': {
      handler(ctx) {
        // Send welcome email
      }
    }
  }
};
Thanks @ngraef, good idea, but it a very significant breaking changes (affect the protocol, as well). So it comes only soonest in 0.15. But we should elaborate it completely and cover all use-cases.
By the way, @derekaug idea is a good workaround. And you can make a middleware with decorates the broker with e sendEvent method which does the emit & broadcast calls & suffixing.
As @derekaug said, the performance would likely be a problem. The workaround could work well in small implementations. For large setups, with thousands of services and even more events flying around, it can be a significant problem.
+1 for this proposal. :)
I will start developing 0.15 soon. To implement this feature, I need concrete suggestions on how to implement it.