You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
defmoduleWorkerdouseOban.Worker@implOban.Workerdefperform(_job),do: :okenddefmoduleTestdouseExUnit.Case,async: trueuseOban.Testing,repo: RepoaliasEcto.Adapters.SQL.Sandboxdescribe"inserting jobs to execute immediately"do# 1test"matches enqueued job by both state & scheduled_at"donow=DateTime.utc_now()Oban.insert!(Worker.new(%{}))assert_enqueued(worker: Worker,state: "available",scheduled_at: {now,delta: 5})end# 2test"matches enqueued job by state only"doOban.insert!(Worker.new(%{}))assert_enqueued(worker: Worker,state: "available")end# 3test"matches enqueued job by scheduled_at only"donow=DateTime.utc_now()Oban.insert!(Worker.new(%{}))assert_enqueued(worker: Worker,scheduled_at: {now,delta: 5})endenddescribe"scheduling jobs in the future"do# 4test"matches delayed job by state=scheduled"donow=DateTime.utc_now()tomorrow=DateTime.add(now,1,:day)Oban.insert!(Worker.new(%{},schedule_in: {1,:day}))assert_enqueued(worker: Worker,state: "scheduled",scheduled_at: {tomorrow,delta: 5})endendend
Click to see the whole script
#!/usr/bin/env elixirMix.install([:ecto_sql,:jason,:postgrex,:oban])Application.put_env(:my_app,Repo,socket_dir: "/run/postgresql",database: "my_app",show_sensitive_data_on_connection_error: true)defmoduleRepodouseEcto.Repo,adapter: Ecto.Adapters.Postgres,otp_app: :my_appenddefmoduleMigrationdouseEcto.MigrationdefupdoOban.Migration.up()endendcaseRepo.__adapter__().storage_up(Repo.config())do:ok->:ok{:error,:already_up}->:ok{:error,error}whenis_binary(error)->raise"can't setup database: #{error}"{:error,error}->raise"can't setup datebase: #{inspect(error)}"endchildren=[Repo,{Oban,repo: Repo,plugins: [Oban.Plugins.Pruner],queues: [default: 10]}]{:ok,pid}=Supervisor.start_link(children,strategy: :one_for_one)Ecto.Migrator.run(Repo,[{0,Migration}],:up,all: true)ExUnit.start()defmoduleWorkerdouseOban.Worker@implOban.Workerdefperform(_job),do: :okenddefmoduleTestdouseExUnit.Case,async: trueuseOban.Testing,repo: RepoaliasEcto.Adapters.SQL.Sandboxsetupdorepo_config=Application.fetch_env!(:my_app,Repo)|>Keyword.put(:pool,Ecto.Adapters.SQL.Sandbox)start_link_supervised!({Repo,repo_config})start_link_supervised!({Oban,repo: Repo,plugins: [Oban.Plugins.Pruner],queues: [default: 10]})pid=Sandbox.start_owner!(Repo,shared: false)on_exit(fn->Sandbox.stop_owner(pid)end)enddescribe"inserting jobs to execute immediately"do# 1test"matches enqueued job by both state & scheduled_at"donow=DateTime.utc_now()Oban.insert!(Worker.new(%{}))assert_enqueued(worker: Worker,state: "available",scheduled_at: {now,delta: 5})end# 2test"matches enqueued job by state only"doOban.insert!(Worker.new(%{}))assert_enqueued(worker: Worker,state: "available")end# 3test"matches enqueued job by scheduled_at only"donow=DateTime.utc_now()Oban.insert!(Worker.new(%{}))assert_enqueued(worker: Worker,scheduled_at: {now,delta: 5})endenddescribe"scheduling jobs in the future"do# 4test"matches delayed job by state=scheduled"donow=DateTime.utc_now()tomorrow=DateTime.add(now,1,:day)Oban.insert!(Worker.new(%{},schedule_in: {1,:day}))assert_enqueued(worker: Worker,state: "scheduled",scheduled_at: {tomorrow,delta: 5})endendend
When I run them, test #1 fails with a confusing message:
1) test inserting jobs to execute immediately matches enqueued job by both state & scheduled_at (Test)
test.exs:77
Expected a job matching:
%{
scheduled_at: {~U[2023-03-22 20:50:12.926871Z], [delta: 5]},
state: "available",
worker: Worker
}
to be enqueued in the "public" schema. Instead found:
[
%{
scheduled_at: ~U[2023-03-22 20:50:12.926792Z],
state: "available",
worker: "Worker"
}
]
code: assert_enqueued(worker: Worker, state: "available", scheduled_at: {now, delta: 5})
stacktrace:
test.exs:81: (test)
The job is clearly there but assert_enqueued/2 fails to match it.
Tests #2 & #3 successfully match this job by state and by scheduled_at, separately. Interestingly enough, test #4 also succeeds by matching a scheduled/delayed job by both state and scheduled_at, so I suppose the issue has something to do with state available.
Expected Behavior
All tests should pass.
The text was updated successfully, but these errors were encountered:
So I've found out that using both state and scheduled_at options forces assert_enqueued/2 to generate the following query:
#Ecto.Query<from j0 in Oban.Job, where: j0.state in ["available", "scheduled"],
where: fragment(
"? BETWEEN ? AND ?",
j0.scheduled_at,
^~U[2023-03-22 21:36:32.819404Z],
^~U[2023-03-22 21:36:42.819404Z]
),
where: j0.state == ^"scheduled", where: j0.worker == ^"Worker",
order_by: [desc: j0.id]>
with an invalid condition state == ^"scheduled". This happens because assert_enqueued/2 builds a Job changeset to process/normalize opts, which in turn would set the scheduled state if opts contain :scheduled_at, effectively overriding the state value given in opts.
You're correct; the tests are generating an invalid query. There's not much of a reason to assert the scheduled time for something currently available, but I think we can still make it work.
The use of `Job.new` to normalaize query fields would change assertions
with a "scheduled_at" date to _only_ check scheduled, never "available".
As a bonus, this also cleans up applying where clauses for assertions.
Closessorentwo#872
Environment
elixir --version
): Elixir 1.14.3 (compiled with Erlang/OTP 25)Current Behavior
Consider these tests:
Click to see the whole script
When I run them, test
#1
fails with a confusing message:The job is clearly there but
assert_enqueued/2
fails to match it.Tests
#2

successfully match this job bystate
and byscheduled_at
, separately. Interestingly enough, test#4
also succeeds by matching a scheduled/delayed job by bothstate
andscheduled_at
, so I suppose the issue has something to do with stateavailable
.Expected Behavior
All tests should pass.
The text was updated successfully, but these errors were encountered: