-
Notifications
You must be signed in to change notification settings - Fork 125
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 instrumentation for repositories #423
Conversation
Interesting, I thought that |
end | ||
end | ||
|
||
def has_event?(event_id) |
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.
meh
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.
From one standpoint, as long as this is repository interface, then it deserves instrumenting. On the other hand what's the value of instrumenting this particular 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.
@pawelpacana check my PR comment, I have big doubt about that one too.
My take on instrumentation, learning on what was in #90. I've started with Robert's idea on instrumented repository, because I wanted something easily deliverable. I believe that higher-level instrumentation still can be interesting in cases different than benchmarking (logging maybe?), but that's some start. Also, I was not sure about instrumenting all public methods of repository, i.e. has_event?(...) - I'm not sure how useful is that instrumentation, except some hardcore benchmarking :P But I guess that in the end, instrumentation is to allow others to play with their ideas how to use it, not only some predefined usecases. What do you guys think? |
let(:test_link_events_to_stream) { false } | ||
let(:test_binary) { false } | ||
|
||
it_behaves_like :event_repository, InstrumentedRepository |
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.
👍
@@ -8,7 +8,7 @@ def initialize(repository: RailsEventStoreActiveRecord::EventRepository.new, | |||
dispatcher: ActiveJobDispatcher.new, | |||
request_metadata: default_request_metadata, | |||
page_size: PAGE_SIZE) | |||
super(repository: repository, | |||
super(repository: InstrumentedRepository.new(repository), |
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.
👍
Regarding which are worth instrumenting -- from maintainer perspective it is better to add less and reconsider adding more in the future than removing published instruments. |
@pawelpacana Which one would you leave? I tend to all except |
Good call, lets drop those two for now. |
These considered not necessary right now, maybe they will be added later. Issue: #244
|
||
let(:test_race_conditions_any) { false } | ||
let(:test_race_conditions_auto) { false } | ||
let(:test_expected_version_auto) { false } |
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.
why false
?
let(:test_race_conditions_any) { false } | ||
let(:test_race_conditions_auto) { false } | ||
let(:test_expected_version_auto) { false } | ||
let(:test_link_events_to_stream) { false } |
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.
why false
here as well ?
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.
Dunno about these, I've initially skipped these values because they've required some additional methods to be defined. I will look at 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.
It doesn't make sense probably to test race conditions but it does make sense to verify that linking events still works correctly, don't you think?
@@ -0,0 +1,48 @@ | |||
module RailsEventStore | |||
class InstrumentedRepository |
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 decorator :)
@@ -43,5 +43,18 @@ module RailsEventStore | |||
expect(published.first.metadata[:request_id]).to eq('dummy_id') | |||
expect(published.first.metadata[:timestamp]).to be_a Time | |||
end | |||
|
|||
specify 'wraps repository into instrumentation' do |
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.
👍
The tests are super verbose...
Allow me to offer some alternative:
I believe these 3 The only downside is that we don't verify |
Good point. I felt the same. But on the other hand... It should be relatively easy to write similar decorators for |
end | ||
end | ||
|
||
def subscribe_to(name) |
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.
As we never unsubscribe, doesn't it lead to memory leaks in all RailsEventStore tests?
Wouldn't these arrays continue receiving payloads for all tests (in this file and other files) which call methods on RailsEventStore::Clients
. It might be better to verify with temporary subscriptions:
callback = lambda {|*args| ... }
ActiveSupport::Notifications.subscribed(callback, /rails_event_store/) do
...
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.
let(:received) { [] }
around do |spec|
callback = lambda {|*args| received << args }
ActiveSupport::Notifications.subscribed(callback, /rails_event_store/) do
spec.call
end
end
or
let(:received) { [] }
around do |spec|
callback = lambda {|*args| received << args }
ActiveSupport::Notifications.subscribed(callback, "#{spec.metadata[:subscription_name]}.repository.rails_event_store") do
spec.call
end
end
specify "instruments append_to_stream", subscription_name: "append_to_stream" do
# ...
end
@paneq mesa like use |
As I've said earlier, I still think higher-level instrumentation can be valuable. As I understand it, instrumentation is not only about performance problems, but also about hooking in the right moment because of some particular usecase we can not think about. Where are you, AOP ;) |
That's unquestionable. It's rather a matter of priorities. Do we start with low-level instrumentation or higher-level.
Interesting. I don't see it much that way because that's only instrumentation and not AOP :) You can't affect the code from within the subscribed code. |
Now, when it doesn't directly on ActiveSupport::Notifications, it can be in RubyEventStore. ActiveSupport::Notifications still is present in the tests, because it serves us as API standard. Issue: #244
@swistak35 any pland for documentation and RDoc? |
@paneq yeah, I haven't started it because I expected that the implementation may change rapidly, I'd prefer to make documentation in separate PR after merge |
good for me :) |
Let's deal with |
Issue: #244