vendure
vendure copied to clipboard
Blocking events api
Is your feature request related to a problem? Please describe. Sometimes I need to perform an additional actions along with standard actions in built-in functions. Thanks to event bus, I could subscribe to an event and do whatever I want. But. Events are fired to subscriptions only and only after transaction completes, which is going to be a problem if I care about data integrity. I don't want to be data committed if my additional operation failed.
Describe the solution you'd like
I'd like to see a type SubscriptionMode = 'non-blocking' | 'blocking'
, like:
this.eventBus.ofType(SomeEvent, 'blocking').subscribe((event) =>
console.log('performed inside transaction');
);
this.eventBus.ofType(SomeEvent, 'non-blocking' /*or omit this argument */).subscribe((event) =>
console.log('performed outside of transaction');
)
I'm not sure whether rx api will be able to emit event in blocking (synchronous) manner, it needs to be researched. Places which event is going to be published should be changed using await:
this.eventBus.publish(new SomeEvent()); <-- was
await this.eventBus.publish(new SomeEvent()); <-- became
Describe alternatives you've considered Prototype patching of core functions. This is also a useful technique, but this could be a problem to patch protected or private functions.
This has come up before but there are 2 major challenges:
- The idea of waiting on async work is IMO not really in line with the observer pattern, which is what the EventBus is aiming to implement.
- Aside from that, the current rxjs-based observable approach makes it (as far as I know) impossible to alert a producer when a subscription function has returned.
But I understand that this functionality could be useful. I'm just not sure how to technically achieve it.
Yeah, I agree. There could be a workaround with rxjs, but seems It'll be not so rubust. What do you think if we'll look at middleware pattern? Like
this.eventBus.use(EventType, async (event, next) => {
await doSmth(); // If doSmth will throw an exception transaction will abort
await next();
})
Closing in favour of
- #2735
which is getting at the same issue. We'll introduce a new method which implements a blocking version of event handling.