Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better way to tap into enqueue? #77

Open
chill-cod3r opened this issue Nov 22, 2020 · 10 comments
Open

Better way to tap into enqueue? #77

chill-cod3r opened this issue Nov 22, 2020 · 10 comments
Assignees

Comments

@chill-cod3r
Copy link

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
Copy link
Contributor

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
Copy link
Author

chill-cod3r commented Nov 23, 2020

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
Copy link
Contributor

Not all internal events translate into domain events

@patrickleet
Copy link
Contributor

patrickleet commented Nov 23, 2020

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
Copy link
Author

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

@patrickleet
Copy link
Contributor

patrickleet commented Dec 3, 2020

@chill-cod3r
Copy link
Author

chill-cod3r commented Dec 3, 2020

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

My understanding 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 function 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.

@mateodelnorte
Copy link

mateodelnorte commented Dec 3, 2020 via email

@chill-cod3r
Copy link
Author

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
Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants