pwightman

pwightman

Hi,

We have a Phoenix/LiveView app, with web servers and separate jobs servers that run Oban Pro. There are 4 jobs servers running.

When we look at our database metrics, what appear to be internal Oban queries seem to dominate the load on our database so we’re trying to understand this better.

At all times, but particularly during load spikes, our load visualizer shows this during a 5 minute period:

As you can see, one query at the top is called 33,384 times in 5 minutes, and it’s this query:

SELECT 
    o0."state", 
    o0."scheduled_at" 
FROM 
    "public"."oban_jobs" AS o0 
WHERE 
    (o0."meta" @> $1) 
    AND (o0."state" != $3) 
    AND (o0."id" < $2) 
ORDER BY 
    o0."id" DESC 
LIMIT $4;

I’ve searched our code pretty exhaustively and I’m unable to find this query, so it seems like it might be internal to Oban.

We’re not sure where to find more information on this (my Google-fu fails me, and might be part of Oban Pro?) to understand why it’s being called this much and how to diagnose/reduce the number of calls, if possible.

Anyone have any ideas?

Showing Posts 1 to 9

sorentwo

sorentwo

Oban Core Team

That looks like the query a Chain worker would use in versions of Pro prior to v1.5. That query is called before each chain job runs, and that can really add up with a busy queue.

The good news is that query is gone and the approach is completely different in v1.5. There’s a description of the change and a small demo in one of the launch week announcements.

pwightman

pwightman OP

This looks like this could really fix our problem, this is wonderful!

We have a large production app that runs LOTS and lots of jobs, I see that 1.5 is a release candidate, but do you feel like it’s pretty stable at this point? Fully ready for production?

Obviously we’ll do our own testing, but just looking for a gut check on how cautious we should be in this upgrade.

Thank you so much for this response!

sorentwo

sorentwo

Oban Core Team

There aren’t any known issues at this point and some larger apps, including the ones we manage, are running it in production. It’s fully ready as far as we know!

atomkirk

atomkirk

We deployed 1.5-rc3 and we’re getting this error. Any ideas?

error] GenServer {Oban.Registry, {Oban, {:plugin, Oban.Pro.Plugins.DynamicLifeline}}} terminating                                                                                                                                                                       ** (ArgumentError) errors were found at the given arguments:                                                                                                                                                                                                             
                                                                                                                                    
  * 1st argument: not a list                                                                                                        
                                                                  
    (erts 15.0.1) :erlang.length(nil)                                                                                                                                                                                                                                        (oban_pro 1.5.0-rc.3) lib/oban/pro/workflow.ex:1300: Oban.Pro.Workflow.to_rescue_operation/1
    (elixir 1.17.2) lib/enum.ex:1703: Enum."-map/2-lists^map/1-1-"/2                                                                                                                                                                                                     
    (oban_pro 1.5.0-rc.3) lib/oban/pro/workflow.ex:1176: Oban.Pro.Workflow.rescue_workflows/2                                                                                                                                                                            
    (oban_pro 1.5.0-rc.3) lib/oban/pro/plugins/dynamic_lifeline.ex:183: anonymous fn/2 in Oban.Pro.Plugins.DynamicLifeline.handle_info/2 
sorentwo

sorentwo

Oban Core Team

That’s new to me :thinking:. It’s mapping the result of a Repo.all, which should always return a list and not nil. Were there any database errors around that time? Did this happen after the initial deploy?

pwightman

pwightman OP

It happens every minute (which is the default interval?), so has been persistent since we deployed 1.5.

On the whole our database load is now a fraction of what it was, so we’re so, so grateful, thank you for continuing to improve this library :pray:

We have a few odd issues that we’re trying to narrow down. One is what Adam mentioned above. It’s not critical, but is an error we’re getting and we’re not sure why. We have a very vanilla configuration, we’re not passing any options.

We are using some regular Oban.Worker and some Oban.Pro.Worker. Does it play nicely with regular Oban.Worker? Should we convert all Oban.Worker to Oban.Pro.Worker?

Another more critical issue is that jobs that are part of some chains or workflows are having their scheduled_at set to 3000-01-01 00:00:00 sometimes. I’ve been trying to narrow down if it’s something we’re doing but I don’t think it is? Here’s one snippet:

  def workflow(listener, meeting, opts) do
    jobs = jobs(listener, meeting, opts)
    deps = Enum.map(jobs, &"action_#{&1.changes.args.action_id}")

    start =
      Workflow.new()
      |> Workflow.add(
        "extract_facts",
        ExtractFacts.new(%{meeting_id: meeting.id})
      )

    jobs
    |> Enum.reduce(
      start,
      fn %{changes: %{args: %{action_id: id}}} = job, acc ->
        Workflow.add(acc, "action_#{id}", job)
      end
    )
    |> Workflow.add(
      "run_analytics",
      RunAnalytics.new(%{meeting_id: meeting.id})
    )
    |> Workflow.add(
      :done,
      AllAutomationsDone.new(%{meeting_id: meeting.id}),
      deps: ["run_analytics" | deps]
    )
  end

For some reason the AllAutomationsDone job gets a scheduled_at of 3000-01-01 00:00:00. I’m not sure if that’s a placeholder value of some sort, but it never recovers, and it’s just stuck there AFAICT.

We also have other jobs that are not part of workflows, but do pass the chain option, such as:

  use Oban.Pro.Worker,
    queue: :sync,
    max_attempts: 2,
    chain: [by: [:worker, args: :integration_id]]

One last oddity is that all our discarded jobs have disappeared, we are permanently at zero jobs in discarded (which is strange always a few known failures happening). They seem to be getting pruned immediately. Still trying to narrow down what’s going on there, but it is definitely new as of the 1.5 release (where I only made the mechanical changes from the Oban Pro 1.5 upgrade docs, which were very helpful).

Also, is this the best place to report these kinds of issues? Happy to move this elsewhere if needed.

sorentwo

sorentwo

Oban Core Team

Alright, that’s something to investigate then.

Fantastic, that’s exactly what we hope for!

There are considerations for regular Oban.Worker in many places, but I strongly recommend using Oban.Pro.Worker consistently. That will allow you to use hooks throughout, if nothing else.

That’s intentional and not a problem at all. Jobs in workflows or chains are put “on hold” using a combination of meta and that scheduled_at timestamp. It’s a psuedo-state used to work around the inflexibility of Postgres enums.

Any job that has dependencies will be put in that on-hold state. When its dependencies run it will be made available to run. That’s all from changes made in Pro v1.4, and it should all be running smoothly at this point.

What is your pruning configuration? The Pruner and DynamicPruner will emit telemetry with counts of how many jobs are pruned at each interval. You can use that to verify how many discarded jobs are being deleted.

This is a great place to report these types of issues—hopefully it helps some other people in the future. If you have something more sensitive you’re welcome to email us instead :slightly_smiling_face:

atomkirk

atomkirk

Heres our dynamic pruner config. We added the discarded key trying to get it to stop deleting our discarded jobs immediately. Please advise:

    {
      Oban.Pro.Plugins.DynamicPruner,
      mode: {:max_age, {14, :days}},
      state_overrides: [
        discarded: {:max_age, {1, :month}}
      ],
      worker_overrides: [
        "Jump.AI.LLM.Jobs.StreamedResponse": {:max_age, {3, :day}},
        ... others just like this ...
      ]
    },

sorentwo

sorentwo

Oban Core Team

Responded in our email chain. I’ll report back here when we understand what’s going on with pruning discarded jobs for your system.

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
apz
I’m new to elixir and just tried to install the elixirLS extension for VScode(ium) and it is throwing some errors that I would like help ...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
georgeguimaraes
Just published claude-code-elixir, a plugin marketplace for Claude Code with Elixir support. These are the plugins I’ve been using for my...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews