-
Notifications
You must be signed in to change notification settings - Fork 57
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
Add queue-based event pub to make sure events are published in order #97
Conversation
58be6ab
to
0b0225b
Compare
lib/sequent/core/event_publisher.rb
Outdated
configuration.event_handlers.each do |handler| | ||
begin | ||
handler.handle_message event | ||
rescue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This rescue can be moved down, this makes the code a bit more readable
def process_events
rescue
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't do that since we don't have a reference to the event at the method body level.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doh, you are right
9344491
to
1de7799
Compare
lib/sequent/core/event_publisher.rb
Outdated
Thread.current[:events_queue] ||= Queue.new | ||
end | ||
|
||
def skip_if_locked(&block) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a better name is skip_if_publishing
or skip_if_not_main_thread
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this a lot 👍 . Makes the intended way of publishing much more clear and explicit.
lib/sequent/core/event_publisher.rb
Outdated
module Sequent | ||
module Core | ||
# | ||
# EventPublisher ensures that, for every thread, events will be published in the order in which they are meant to be published. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think "... will be published breadth (or width) first" is better.
To clarify, with breadth first I mean: first all first level events than the consequences of those events.
lib/sequent/core/event_publisher.rb
Outdated
# | ||
# If you do not want this, you are free to implement your own version of EventPublisher and configure sequent to use it. | ||
# | ||
class EventPublisher |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am thinking to split this in 2 concerns. This might help in understanding the concepts better and might be easier to extend with other strategies. This also allows us to support the current behavior and be backward compatible.
- The Events queue with is basically
process_events
- The FIFO strategy" which is basically
events.each { |event| events_queue.push(event) }
.
When someone want LIFO (or depth first) the event should be prepended to the Queue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should hold off on implementing something like this until someone asks for it / needs it.
private | ||
|
||
def events_queue | ||
Thread.current[:events_queue] ||= Queue.new |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Queue only supports FIFO I think. We can safely use Array here to support both FIFO and LIFO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should hold off on implementing something like this until someone asks for it / needs it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are changing the current behavior so I think it is good to support both cases and the current one as default, with maybe a warning message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neither of those scenarios is the current one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes you are right... Okay, let's communicate this in the changelog when we release.
lib/sequent/core/command_service.rb
Outdated
end | ||
ensure | ||
repository.clear | ||
commands.each do |command| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be a one-liner: each. {}
@@ -57,6 +46,31 @@ def remove_event_handler(clazz) | |||
|
|||
private | |||
|
|||
def process_commands |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we extract this to a separate class like the EventPublisher. Both are quite similar in intent and behavior. Same suggestion made for the EventPublisher also apply here then :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CommandService
is a separate class like EventPublisher
already.
ea52ad9
to
e7eb2fc
Compare
e7eb2fc
to
1d55cc4
Compare
@erikrozendaal @s0meone @bjpbakker feedback? We will be merging this shortly. |
I do like this change, it solves a bunch of problems with published event ordering. That said, current behavior is changed quite a lot, and may actually break current implementations. Most likely the tests won't cover this (because often they simply assert published events). That makes it tough to keep production code bases that are not in active development up to date with sequent. Can we provide the current behavior via a configuration option? |
This behaviour is configurable to a certain degree: One is free to simply implement her own version of I'd rather we not officially support the legacy behaviour and the code that goes along with it. If we get questions about this I'd be more than happy to help people gut |
I think also that we should release this with a minor level version number increase to indicate that there is new functionality being introduces. This would be version 1.1.0. |
If we choose to no longer support the current order of event publishing (and stick with semantic versioning) we should bump to 2.0. This change currently is not backwards compatible. |
That depends on your definition of "backwards compatible". Every change is potentially backwards incompatible, yet we don't increment major version number for every single bugfix. The question is whether the new ordering is compatible with the old ordering. The answer is: that depends on how our users have implemented their systems and to what degree they are dependent on the old ordering. I suspect that most of them are not, making it for most (or all) users a backwards compatible change. Or do you suspect that this will break functionality for a non-trivial percentage of Sequent users? |
Running additional (event handler) generated commands in the same transaction may lead to huge, complicated transactions. This may not be what we want. But I guess handling new commands in separate transactions requires a lot of additional infrastructure (persistent queues, background jobs, etc). So I guess this is fine, but I think we should discourage people from generating new commands in event handlers for immediate execution. |
@bjpbakker let's talk about version numbers on Friday. Merging this since that isn't a blocking issue. |
Run the included spec on
master
to see what happens without the newEventPublisher