mardi 23 juin 2020

NodeJS Service Layer asynchronous communication

If I have to invoke ServiceB.action as a result of ServiceA.action being invoked, should I call ServiceB.action from ServiceA.action at the appropriate time, or should I emit an event from ServiceA and let ServiceB react to that event?

I can use an EventEmitter, but it works synchronously, in a sense that the callbacks are invoked sequentially without waiting the previous to resolve, which is ok for me. What isn't, though, is that the $emit will not wait until all of the listeners have resolved.

For a more real world scenario, lets assume that I have a Subscription service, and when a new subscription is created, the Email service needs to know about it so that it can notify somebody by email.

const SubscriptionService = {
  async create(user) {
    await Subscription.create(user)
   
    // Notify email service
  }
}

const EmailService = {
    async notify(user) {...}
}

One way I could do it, is call the EmailService.notify(user) from SubscriptionService.create and pass in the user.

Another way I could do it is with an event emitter

async create(user) {
    await Subscription.create(user)

    Emitter.$emit('subscription', user)
}

The second approach seems clean, because I'm not mixing things together, the notifications happen as a result of the subscription being created and the create method is not polluted with extra logic. Also, adding more side-effects like the notification one would be simpler.

The subscription service's create method, however, will not wait until all of the listeners have resolved, which is an issue. What if the Notification fails? The user will not get the email, in this scenario. What about error handling? In the first scenario I can handle the errors on spot when I invoke the EmailService.notify, but not with the emitter.

Is not meant for similar use-cases or am I looking at the problem in a wrong way?

Aucun commentaire:

Enregistrer un commentaire