-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Change internal mapping for event subscriber registrations #3758
Change internal mapping for event subscriber registrations #3758
Conversation
310ef32
to
75e0d99
Compare
91eaf64
to
a20b488
Compare
2cfe4be
to
1304862
Compare
a090359
to
1bbe5b1
Compare
The new method `Spree::Event.subscribe_subscribers!` is introduced in Solidus with solidusio/solidus#3758 as a better way to subscribe event subscribers. Under the hood, event subscribers use new interal mappings. We need to keep around the old interface as well until it won't be supported anymore in Solidus.
The new method `Spree::Event.subscribe_subscribers!` is introduced in Solidus with solidusio/solidus#3758 as a better way to subscribe event subscribers: under the hood, event subscribers use new interal mappings. Also, we need to keep around the old interface as well until it won't be supported anymore in Solidus.
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.
Left some comments, I think we are close to a solution, thanks @spaghetticode !
core/lib/spree/event/subscriber.rb
Outdated
send event_action, event | ||
} | ||
subscription = Spree::Event.subscribe(event_name) { |event| send event_action, event } | ||
# old mappings, to be removed when Solidus 2.10 is not supported anymore: |
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 use the word deprecated instead of old
? Just because it will be easier to find it if we perform a search of all the deprecated code within the codebase with a text editor.
core/lib/spree/event/subscriber.rb
Outdated
subscription = Spree::Event.subscribe(event_name) { |event| send event_action, event } | ||
# old mappings, to be removed when Solidus 2.10 is not supported anymore: | ||
send "#{event_action}_handler=", subscription | ||
# new mappings: |
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 can get rid of this comment, probably improving a little bit the one with the deprecated code to explain that this other way is the new way of doing things.
@@ -14,7 +14,9 @@ module Preferences | |||
# | |||
# @deprecated | |||
def reset_spree_preferences(&config_block) | |||
Spree::Config.instance_variables.each { |iv| Spree::Config.remove_instance_variable(iv) } | |||
Spree::Config.instance_variables. | |||
reject { |iv| iv == :@events_configuration }. |
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'm not sure about this. What if some specs need to reset that configuration? It's applicable? How do people know that all the preferences except that one will be reset when calling reset_spree_preferences
in their code?
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 helper method is deprecated, so it won't be around for long. We don't use it anymore in our codebase, but we have some specs that verify its behavior. I'm not sure if creating a better workaround for making it work properly with the new event mappings is worth the effort at this point.
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.
Oh right, it's deprecated. 👍
core/lib/spree/core/engine.rb
Outdated
Spree::Event.subscribers.each_key do |klass| | ||
klass.constantize.subscribe! | ||
end | ||
Spree::Event.subscribe_subscribers! |
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 more I look into this and the more I think we need another class called Spree::Event::Subscribers
that acts as a collection of subscribers. No matter if it's hash inside but the interface will probably look better, having something like:
Spree::Event.subscribers.subscribe_all
.
WDYT?
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.
sure, makes sense! I'll work on your suggestion 👍
@@ -54,7 +54,14 @@ def self.included(base) | |||
# end | |||
# end | |||
def event_action(method_name, event_name: nil) | |||
mattr_accessor "#{method_name}_handler" | |||
mattr_writer "#{method_name}_handler" |
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 don't we need to deprecate the writer 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.
We still use the writer internally to keep compatibility, if somebody is still using the reader in their codebase (we don't use the reader anymore). So, if we deprecate the writer, then we'll need to silence the deprecation when using it. So, deprecating the writer would be impractical at this point.
But I think we don't really need to deprecate the writer as well. The only reason for some developers to be using the writer in their codebase is to set a value to be accessed from the reader. When this happens, they will see the deprecation when the matching reader is called.
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.
Makes sense, thanks Andrea.
1bbe5b1
to
c49b9f5
Compare
2c48a9f
to
be6e796
Compare
be6e796
to
b2a8847
Compare
core/lib/spree/event/subscriber.rb
Outdated
event_actions.keys.each do |event_action| | ||
Spree::Event.unsubscribe send("#{event_action}_handler") | ||
end | ||
Spree::Deprecation.warn("#{name}.unsubscribe! is deprecated. Please move your event subscribers to folder `app/subscribers/*_subscriber.rb` and they will be unloaded automatically. ", caller) |
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 the message here is incorrect. You have to delete the subscriber file to unsubscribe, isn't it? Also, I'd keep the method since maybe you don't have control over where the file has been added (core or an extension).
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're right about the message. And also the remainder of the comment is right. I think we need to keep offering that kind of granularity, even though it will be rarely used.
b2a8847
to
0fa6598
Compare
5d36a67
to
465a8bf
Compare
880bcde
to
996bd4f
Compare
The class `Spree::Event::SubscriberRegistry` is introduced in order to centralize and handle in a dedicated environment event mappings for subscriber modules. This was previously responsibility of each `Spree::Event::Subscriber` module, but due to some issues with Zeitwerk and the way these modules were activated in rails initializers, that approach is not working properly anymore with Rails 6. This class also manages the activation/deactivation of all event subscribers that happens at boot time. The activation/deactivation code is threadsafe, just in the remote case that somebody tries to use it in a multithreaded context. This does not happen in the standard use-case of this class, as it is being used during the app initialization time.
Subscribers are loaded once at runtime during the app initialization process, so if they get reset by `reset_spree_preferences` then the original value will not come back.
996bd4f
to
6816374
Compare
The event config setting `Spree::Event.config.subscribers` (accessible via Spree::Event.subscribers) is now deprecated in favor of the new subscriber registry.
`Spree::Event.subscribers` is deprecated and its functionality is replaced by `.subscriber_registry`. `.subscriber_registry` is not a 100% compatible replacement for `.subscribers`, as the internal mapping system for event subscribers is changing completely, but for existing Solidus stores the change should be transparent enough. `Spree::Event.require_subscriber_files` is deprecated and delegated to the subscriber registry object. The method with the same name defined in `Spree::Event::SubscriberRegistry` is now private, as there is no use in keeping it public.
As `Spree::Event.subscribers` is deprecated and being replaced by `Spree::Event.subscriber_registry`.
`Spree::Event::Subscriber.subscribe!` is deprecated and replaced by `::activate`. `Spree::Event::Subscriber.unsubscribe!` is deprecated and replaced by `::deactivate`. The method names `subscribe` and `unsubscribe` are already used by `Spree::Event`, so the naming was a bit confusing; `activate` and `deactivate` should help in making this a bit more clear. `::activate` and `::deacticate` are now using the new subscriber registry for activation/deactivation, as `Spree::Event.subscribers` is now deprecated.
We're keeping the old event mappings handler methods, as somebody may still be relying on them, but they're now deprecated.
6816374
to
6e96808
Compare
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.
Found something that looks like a mistake, let me know if I'm missing something instead.
The methods `Spree::Event.activate_autoloadable_subscribers` and `Spree::Event.deactivate_all_subscribers` encapsulate in a single call all the logic needed to activate event subscribers during the app init process. Those methods will need to be used also in the engine.rb file provided by the gem `solidus_support`.
c49b9f5
to
b2a5a03
Compare
The new method `Spree::Event.activate_all_subscribers` is introduced in Solidus with solidusio/solidus#3758 as a better way to subscribe event subscribers. Under the hood, event subscribers use new interal mappings. Also, we need to keep around the old interface as well until it won't be supported anymore in Solidus.
@kennyadsl thanks for spotting the bug ❤️ I have just tested this PR with a newly generated sandbox app using |
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.
Thanks @spaghetticode!
The new method `Spree::Event.activate_all_subscribers` is introduced in Solidus with solidusio/solidus#3758 as a better way to subscribe event subscribers. Under the hood, event subscribers use new interal mappings. Also, we need to keep around the old interface as well until it won't be supported anymore in Solidus.
I'm getting these deprecations while running a generator (although I don't believe that to be relevant), I think the caller should be refined to point at the right level of the backtrace, instead of showing
Unless I'm mistaken and this is correct for some reason we should probably turn this comment into an issue |
Fixes #3757
The previous way of registering subscribers could generate some issues with rails 6 applications, due to how Zeitwerk (re)loads classes in initializers. The previous approach was also scattering the information into every single subscriber, while now it's centralized in a single place.
Currently,
Spree::Event.subscribers
includes only the list of subscriber classes, while the rest of the information is delegated to each subscriber. This is how information can be accessed with the current interface:After merging this PR, the functionality provided by
Spree::Event.subscribers
will be managed by the newSpree::Event.subscriber_registry
. The registry stores information with the format:Real world example:
This PR requires a small change in solidus_support too, see solidusio/solidus_support#53
These changes should be transparent to stores as they only modify how event subscribers are mapped and managed internally in Solidus.
Many thanks to @cedum and @DanielePalombo who helped in moving forward the PR.
Checklist: