lamxw2

lamxw2

Hi there. I am currently working on migrating our current queue system from GenServers to Oban (Pro). I am implementing this in phases, so not all entities will be running in Oban yet, which means based on a condition, some entities use our existing queue, and the remainder get queued in Oban.

We want to prioritize the entities using our existing queue system, so the plan was to pause the relevant Oban queues when the current queue is not empty, then resume Oban queues when that queue is empty.

However, I have run into Ecto.StaleEntryError

Last message: {:notification, :signal, %{"action" => "pause", "ident" => "any", "queue" => <omitted>}}
Last message: {:notification, :signal, %{"action" => "resume", "ident" => "any", "queue" => <omitted>}}

I have tried:

  1. Using Oban.check_queue and pause/resume based on queue.paused value, however that requires a db query call every time an entity is queued, which is not very efficient. StaleEntryError occurs
  2. Adding a boolean field oban_paused to my GenServer states, this prevents a db query every time. However we have multiple GenServers that share a queue, so the oban_paused boolean is inaccurate based on the queue. This also still has a StaleEntryError on a specific GenServer that doesn’t share a queue, so it seems like our system is too quick and a race condition happens as well.
  3. Wrapping Oban.pause/resume_queue in a try catch, but this doesn’t work either.

The next solution I thought of doing was manually pausing (changing the state) Oban.Job instead of the queue itself, which I think would work out better especially for our GenServer states that share a queue, since we rate limit and partition our queues based on that. However, I don’t see a suitable state that can be used, aside from scheduled, but that would require setting a time for the Job, which isn’t suitable for our use case.

I am looking for an easy workaround, because we won’t need to resume/pause queues like this after our entire current system has been moved to Oban.

Any other suggestions are welcome!

Showing Posts 1 to 10

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

Would using the built in priority feature work here instead of trying to juggle priority yourself via pausing and unpausing?

lamxw2

lamxw2 OP

Nope it would not, because our entities have already occupied those priorities.

For the specific part that you quoted, we are “juggling” the priority ourselves because we don’t want those entities to use Oban for the time being, since we are moving them to Oban in phases.

Basically, we have entities with our own assigned priorities from 1 to >1000, with the lower number being the highest priority. Since moving an entire system is tricky, we want to move only internal priorities 300 and above to Oban, while keeping internal priorities <300 on our current system. These 1-1000+ priorities are grouped according to Oban’s 0-9 priorities.

sorentwo

sorentwo

Oban Core Team

The Ecto.StaleEntryError you’re getting is from a bug in DynamicQueues that was fixed in the rather recent Pro v1.5.0-rc.4.

Note that Oban.check_queue doesn’t query the database. It returns information directly from the queue’s producer process.

The easiest workaround is to upgrade to the latest RC (it’s stable, no known bugs at this point) and avoid the annoying StaleEntryError bug :slightly_smiling_face:.

lamxw2

lamxw2 OP

The Ecto.StaleEntryError you’re getting is from a bug in DynamicQueues that was fixed in the rather recent Pro v1.5.0-rc.4.

Hi, you may remember me from this post Getting StaleEntryError on DynamicQueues.update :smile:

I have been on the latest Oban Pro rc version ever since then, but unfortunately am facing this error now.

sorentwo

sorentwo

Oban Core Team

Of course :slightly_smiling_face:

You’re positive it’s rc.4? The issue was reproducible in tests and there were numerous logic changes, including a rescue for that specific exception.

lamxw2

lamxw2 OP

You’re positive it’s rc.4? The issue was reproducible in tests and there were numerous logic changes, including a rescue for that specific exception.

Yes, I’m positive. In my mix.lock, the version is 1.5.0-rc.4. Unless the mix.lock isnt an accurate indicator?

sorentwo

sorentwo

Oban Core Team

No, that’s an accurate indicator. I’m not sure how you’re still seeing that error then. Which mechanism are you using to pause? Will you share your current code?

dimitarvp

dimitarvp

Just to remove all variables, did you do these steps?

rm -rf _build deps
mix do deps.get, compile

And then try again?

lamxw2

lamxw2 OP

I had not, but I just tried and it didn’t resolve it unfortunately

lamxw2

lamxw2 OP

Which mechanism are you using to pause? Will you share your current code?

Just pausing the queue based on the queue name. Sure. I have also included the other code I tried as commented out code

1st module

  defp pop_and_send(%{queue: _queue, name: _name, priority_queue: []} = state) do
    ObanQueue.use_oban?() |> maybe_resume_oban_queues(state)
  end

  # to modify when high priority entities are moved to oban
  defp pop_and_send(%{name: name, priority_queue: priority_queue} = state) do
    # IO.inspect(state.oban_paused, label: "oban_paused when priority queue not empty")

    # Pause when `priority_queue` is not empty
    if ObanQueue.use_oban?() and !state.oban_paused, do: ObanQueue.pause_queue(name)
    # if ObanQueue.use_oban?() do
    #   queue = Oban.check_queue(queue: ObanQueue.set_queue(name))
    #   if !queue.paused, do: ObanQueue.pause_queue(name)
    # end

    # ... <logic involving our existing system here>

    %__MODULE__{state | priority_queue: priority_queue, oban_paused: true}
  end

  # check if queue is paused first
  defp maybe_resume_oban_queues(true, %{name: name, oban_paused: true} = state) do
    ObanQueue.resume_queue(name)

    %__MODULE__{state | oban_paused: false}
  end

  defp maybe_resume_oban_queues(true, %{oban_paused: false} = state), do: state

  defp maybe_resume_oban_queues(false, %{queue: queue, name: name, priority_queue: []} = state) do
    case Qex.pop(queue) do
      {:empty, _queue} ->
        state

      {{:value, pid}, queue} ->
        # ... <logic involving our existing system here>

        %__MODULE__{state | queue: queue}
    end
  end

ObanQueue module

@doc "Resume queue based on SSP"
  # def resume_queue(ssp) do
  #   try do
  #     Oban.resume_queue(queue: set_queue(ssp))
  #   catch
  #     type, reason ->
  #       error = Exception.format(type, reason, __STACKTRACE__)
  #       Logger.warning("Blah blah #{error}")
  #       :ok
  #   end
  # end

  def resume_queue(ssp), do: Oban.resume_queue(queue: set_queue(ssp))

  @doc "Pause queue based on SSP"
  # def pause_queue(ssp) do
  #   try do
  #     Oban.pause_queue(queue: set_queue(ssp))
  #   catch
  #     type, reason ->
  #       error = Exception.format(type, reason, __STACKTRACE__)
  #       Logger.warning("Blah blah #{error}")
  #       :ok
  #   end
  # end

  def pause_queue(ssp), do: Oban.pause_queue(queue: set_queue(ssp))

set_queue is a function that just identifies the queue name based on the variable

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
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
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
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
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews