-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Fixup have_enqueued_job matcher on job retries
#2573
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
Conversation
f6316ca to
ab03c3d
Compare
|
hmm.. Actually looking @ CI, 6.0 is green, so probably failure is rails-6.0 <-> ruby-3.1 compat locally. And 5.2 fails with |
f6b2620 to
be0b3b7
Compare
|
It became more complicated due to rails-6.0 pushing jobs with the same |
|
We've merged build fixes for Rails and updated the minimum versions so this should be ok to be rebased without your ci changes |
be0b3b7 to
c308f61
Compare
|
🙇 done |
pirj
left a comment
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!
1de9d7d to
0cd7393
Compare
|
😿 |
0cd7393 to
30ba268
Compare
2625570 to
304f624
Compare
This comment was marked as outdated.
This comment was marked as outdated.
| in_block_jobs = queue_adapter.enqueued_jobs.drop(original_enqueued_jobs_count) | ||
|
|
||
| check(in_block_jobs) | ||
| in_block_jobs = queue_adapter.enqueued_jobs.each_with_object({}) do |job, jobs| |
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 appears to me that storing by the hash key is not necessary.
I've added a couple more jobs of the same kind, and they have a different job_id assigned, resulting in a different hash.
As a result, count is always a 1.
Below, a -= 1 and a further .positive? with Array.new and a compact is basically subtraction of previously enqueued jobs from all enqueued jobs.
I dared pushing a commit that compares with a Set#-.
Can you write a failing spec to prove this approach is insufficient?
pirj
left a comment
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.
Needs a test that would fail without changes, so that changes would make it green.
|
The previous implementation was:
Of course, since the matcher is scoped to one specific job class, it's quite an edge case. This (previous, before the PR's) implementation was not considering jobs that were at the bottom of the list, and moved to the top of the list, e.g.: - job with args [1]
- job with args [2]
+ job with args [1]
+ job with args [2]And Equally, if the order of jobs would change, or if some jobs succeed, or if more jobs succeed than fail and a re-scheduled, the expectation would fail. I believe we can leave some of those cases for follow-up improvements, but one I'd love to see is: # some setup
expect { ... }.to have_enqueued_job(MyJob)that would fail if we just compare the counts of matching jobs. It is unfair to do so with counts because yes, one job was performed, and one enqueued. How about an example with a job that was on |
|
This looks fine to me, but I defer to @pirj as we do want a failing spec this fixes :) |
This is an incorrect assumption. The "before" for the matcher is everything prior to what is inside the So if a job is enqueued, performed and schedules itself all inside in_block_jobs = queue_adapter.enqueued_jobs.drop(original_enqueued_jobs_count)and all the jobs that are left enqueued (e.g. when Even though I'd love to merge my shiny refactoring involving I failed to write an example that would break the existing implementation, and with this I'm more inclined to close this PR. Please do not hesitate to reopen if you can write a failing spec. |
|
Actually, a spec might be possible to write with a direct non-block usage of |
|
@ojab Does this look correct to you? |
|
@pirj oh, right, sorry for bogus spec. I'll update the PR tomorrow to use non-block form and will check that it fails properly in master. |
|
Checked the commit where monkeypatch was introduced into local codebase, it's retried_job.perform_later
expect { perform_enqueued_jobs }.to so yeah, spec is indeed doesn't mirror what was broken 🤦 |
8b111e9 to
a9d666a
Compare
|
Which monkey patch? How does this work? queue_adapter.perform_enqueued_jobs = true
end
it "passes with reenqueued job" do
time = Time.current.change(usec: 0)
retried_job.perform_later
travel_to time do
expect { perform_enqueued_jobs }.toI strongly prefer the solution with |
Previously we were checking only job counts, so if one job was performed and one job was added - matcher failed. Check by unique id (`#hash`) instead. We cannot use `job['job_id']` here, because job retains `job_id` on retry. Also we need to count jobs before & after because multiple `#perform_later` in rails-6.0 create jobs with the same `#hash`, at least in some cases, using `:test` AJ adapter.
a9d666a to
47f15d2
Compare
|
Thank you, @ojab ! |
Fixup `have_enqueued_job` matcher on job retries
|
Released in 6.0.2 |
Previously we were checking only job counts, so if one job was
performed and one job was added - matcher failed. Check by unique
id (
#hash) instead.We cannot use
job['job_id']here, because job retainsjob_idon retry.This works only with
rails >= 6.1, becauseretry_onwas introduced in 6.0 and apparentlytestqueue adapter is broken for retries in 6.0: it adds executed job back with addedexception_executionsalong with actual retried job. So dunno how to proceed here, please advise /shrugTest CI run: https://github.com/ojab/rspec-rails/runs/5183906574?check_suite_focus=true
Also:
fixes #2668