-
Notifications
You must be signed in to change notification settings - Fork 131
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 support for ActiveSupport
classes in Sidekiq::Worker
methods
#2104
base: main
Are you sure you want to change the base?
Add support for ActiveSupport
classes in Sidekiq::Worker
methods
#2104
Conversation
…and #perform_in methods As stated in the [code docs](https://github.com/sidekiq/sidekiq/blob/e411ffc78713099a90b348930d0b664d2ee41279/lib/sidekiq/job.rb#L256-L261): "+interval+ must be a timestamp, numeric or something that acts numeric (like an activesupport time interval)."
I don't think we can assume that. It doesn't depend on Rails and this will lead to type checking errors. |
ActiveSupport
classes in Sidekiq::Worker
methods
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.
Hey @iMacTia, thanks for contributing this!
As Kaan mentioned, we can't assume that ActiveSupport and/or Rails are available. Luckily, this check already exists in ActiveSupportTimeExt
. Could you please modify your PR to use that logic, and approach the appropriate time type?
tapioca/lib/tapioca/dsl/compilers/active_support_time_ext.rb
Lines 40 to 51 in 2dcdda3
ConstantType = type_member { { fixed: T.class_of(::Time) } } | |
sig { override.void } | |
def decorate | |
return unless constant.respond_to?(:zone) | |
root.create_path(constant) do |mod| | |
return_type = if ::Time.zone | |
"::ActiveSupport::TimeWithZone" | |
else | |
"::Time" | |
end |
Thank you both for reviewing, I figured this might be an issue hence why I pointed it out in the description. |
@KaanOzkan @amomchilov I'm hitting a bit of a bump with testing both scenarios ( I think I found a working solution in my latest commit, but I'm not very proud of the If you have any suggestion I'm happy to make amendments or if it works and you don't mind we could just merge it as-is 🙂 |
All tests except for one (unrelated?) are currently passing on my branch 🎉 |
sig { void } | ||
def backup_activesupport | ||
Object.const_set(:ActiveSupportBackup, Object.send(:remove_const, :ActiveSupport)) # rubocop:disable RSpec/RemoveConst | ||
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.
Another way is to use SpecWithProject
similar to CLI tests. You'll be running it in a test gem so it should be a matter of requiring and not requiring ActiveSupport
. But this way will be slower.
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.
Soooo which approach do you think we should be using in this case?
I got it working with the current approach, but it's your gem so it's really up to you how you'd like this to be tested 🙂
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 don't have a strong opinion, if after_teardown
doesn't run somehow we probably have more important issues than not resetting ActiveSupport
. I'll leave it to @amomchilov
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.
None of this is needed, you can include Tapioca::Helpers::Test::Isolation
into this test class to make each of the tests run in a forked subprocess, each with its own clean copy of the object space.
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.
Aaaah now we're talking! I'll give that a try, thank you @paracycle!
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 also couldn't figure out how to run a single or a subset of tests, that would be quite useful because right now I can only run the whole test suite which takes quite some time 😞
Never mind, I finally found bin/test
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.
OK it wasn't super straightforward because active_support
is actually required in bin/test
(apparently for Rails 6 support?) and so it's already part of the object space at the time of forking. That means I still need to undefine and unload it, but at least I don't need to put it back after the tests have run 👍
I grabbed some code from pipeline_spec.rb
to do that and tests are passing locally 🙌
Motivation
The currently tapioca-generated signatures for
Sidekiq::Worker
methods do not supportActiveSupport
classes.But reading the code comments and testing the behaviour at runtime, the methods should indeed be able to support them.
Implementation
ActiveSupport
classes have been added to#perform_at
and#perform_in
methods, keeping their semantic difference despite these being aliased:ActiveSupport::TimeWithZone
as an allowed type to#perform_at
ActiveSupport::Duration
as an allowed type to#perform_in
This is based on the assumption that projects using Sidekiq are most likely Rails application and therefore have access to ActiveSupport. If we don't want to rely on that assumption, the implementation will need to be tweaked to check if the ActiveSupport classes are defined when generating the signatures.
Tests
No new tests, just amended the existing tests to make sure the signatures are generated correctly