-
-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Fixup have_enqueued_job
matcher on job retries
#2573
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 |
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.
|
||
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?
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 }.to I 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_id
on retry.This works only with
rails >= 6.1
, becauseretry_on
was introduced in 6.0 and apparentlytest
queue adapter is broken for retries in 6.0: it adds executed job back with addedexception_executions
along 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