servicebus / rabbitbus-model-service-template

0 stars 0 forks source link

Better way to tap into `enqueue`? #77

Open chill-cod3r opened 3 years ago

chill-cod3r commented 3 years ago

This is somewhat of just a question, but I noticed all of the SourcedEntity models emit events, however I don't see them used very much if at all. I also see that .enqueue is a way to hold off on emitting those events until after a commit (the way it currently works with eventsToEmit being manually iterated through by the repository requires implementation at repository level but I think that makes sense).
Right here: https://github.com/servicebus/rabbitbus-model-service-template/blob/master/handlers/list.item.add.mjs#L50 in your handler you're essentially manually performing what could be fired off from the sourced-repo-mongo's iteration through eventsToEmit right? Would it ever make sense to provide a way to "tie" the model's .emit method directly to something like bus.publish? That way the event publishing would just automatically happen here: https://github.com/mateodelnorte/sourced-repo-mongo/blob/master/index.js#L264 I'm not sure if this would make sense or if there's other reasons you wouldn't want to do this or if I'm not understanding what the purpose of .enqueue is properly. Any explanation / advice would be much appreciated!

patrickleet commented 3 years ago

emit will emit events right away, while enqueue will wait for the repository to be committed successfully before emitting.

This allows you to make sure a transaction is completed and committed before the events are published out.

chill-cod3r commented 3 years ago

That makes sense. Is enqueue more for ensuring transaction completion at the code level? I’m not sure how to phrase what I am asking better but basically here’s my raw idea -

Using es6 classes, I want to override the ‘emit’ function on the subclass - my entity such that when enqueue’d events “fire off” the ‘eventsToEmit’ items in https://github.com/mateodelnorte/sourced-repo-mongo/blob/master/index.js#L264 it will just go ahead and fire those off to a bus instead.

Thinking about that raw idea as a possibility I was wondering if you had thought of that and whether or not you thought it was a terrible idea. My argument against myself in this situation would be to just listen for the enqueued events in my handler code block and fire off the bus there(pretty much what your boiler plate repo here does minus the “wait on enqueue events” part), and that maybe injecting a bus into an entity is too much coupling

patrickleet commented 3 years ago

Not all internal events translate into domain events

patrickleet commented 3 years ago

here's an article that came up on google: https://www.innoq.com/en/blog/domain-events-versus-event-sourcing/

I didn't read the whole thing but sourced is an event sourcing framework, event sourcing happens at the aggregate level - bus.publish publishes a domain event that other services can subscribe to, typically we use this for CQRS.

So enqueue is basically saying, once the transaction is committed to the repository, emit these local events - you could then subscribe to those local events to make sure they happen, and in response publish a domain event.

I think the example just isn't great because it doesn't do that.

here's a better snippet from a handler:

let eStore = new EStore()

// enqueued, fires when commit is successful
eStore.on('initialized', (initializedEStore) => {
  bus.publish('eStore.initialized', { eStore: initializedEStore })
  log.info({ msg: 'eStore.initialized', eStore: initializedEStore })
  done()
})

initializeEStore(eStore, { name, url, platform, platformOptions })

try {
  await eStoreRepository.commitAsync(eStore)
} catch (error) {
  log.error({ msg: 'Error while committing repository', error })
  throw new Error(`Error while committing repository - ${error.message}`)
}

If there was an error committing the repository, then the initialized event would never be published locally, and the domain event wouldn't be fired erroneously.

chill-cod3r commented 3 years ago

Awesome! That wraps up the explanation really well. Thank you for that!

patrickleet commented 3 years ago

I forgot I wrote about this here

https://hackernoon.com/complicated-patterns-arent-always-that-complicated-usually-it-s-the-simple-ones-that-bite-you-caf870f2bf03

chill-cod3r commented 3 years ago

Yes - that's actually the article that sparked my seeking out further understanding of enqueue.

My understanding in summary:

Thanks again for all the responses. I actually wrote a new repo leveraging sourced with dynamodb + lambdas. it's not 100% complete (i didn't bother to implement commitAll and getAll) I'm not sure i'll "take it all the way" but it greatly helped me understand all the pieces and all feels very familiar now. I feel like there's so many repo possibilities but I see how mongo specifically excels at it.

mateodelnorte commented 3 years ago

This is all correct! Thanks and feel free to publish your new repository. We’ll be happy to link to it.

On Wed, Dec 2, 2020 at 7:40 PM John Wolfe notifications@github.com wrote:

Yes - that's actually the article that sparked my seeking out further understanding of enqueue.

So in summary:

  • enqueue is mainly leveraged by a repository - most commonly the sourced-repo-mongo
  • it is used by calling it in a property update on an Entity
  • it is leveraged by having the repo "fire off" enqueued events after a successful commit
  • it is useful because if the enqueued event gets fired, then a transaction-type workflow can safely move to it's next required step because you know everything is saved successfully up to that point
  • it is not necessarily tied to event bus type events that radiate through an entire system, but it could be used to key off of to emit certain bus type of events situationally if it makes sense for the use case

Thanks again for all the responses. I actually wrote a new repo leveraging sourced with dynamodb + lambdas. it's not 100% complete (i didn't bother to implement commitAll and getAll) I'm not sure i'll "take it all the way" but it greatly helped me understand all the pieces and all feels very familiar now. I feel like there's so many repo possibilities but I see how mongo specifically excels at it.

— You are receiving this because you were assigned.

Reply to this email directly, view it on GitHub https://github.com/servicebus/rabbitbus-model-service-template/issues/77#issuecomment-737603110, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEHOX3AREN72DG7O44PLTLSS3UATANCNFSM4T6HWA3A .

chill-cod3r commented 3 years ago

Awesome - published

https://www.npmjs.com/package/sourced-repo-arc-dynamo

It has 1 pretty large dependency right now - using it in an https://arc.codes project with automatic setup of dynamo connection client, having to have the tables already pre-established, and using the @architect/functions package to leverage dynamo client functionality. I have a plan to rip that out of eventually but this got me up and running and actually works! Was very exciting to at least deploy and get working

patrickleet commented 3 years ago

A postgres repo that uses json data type to store docs would be great.

Matt made one years ago for a client but it's lost I believe.