vendure icon indicating copy to clipboard operation
vendure copied to clipboard

Blocking events api

Open ashitikov opened this issue 2 years ago • 2 comments

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.

ashitikov avatar Aug 30 '22 09:08 ashitikov

This has come up before but there are 2 major challenges:

  1. 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.
  2. 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.

michaelbromley avatar Sep 16 '22 15:09 michaelbromley

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();
})

ashitikov avatar Sep 16 '22 16:09 ashitikov

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.

michaelbromley avatar Mar 18 '24 13:03 michaelbromley