mspanc

mspanc

Membrane Core Team

Hello,

I’ve just published 1.0.0 of Jumbo - a new job queueing library: GitHub - mspanc/jumbo: Reliable, OTP-style, lightweight job processing queue for the Elixir language · GitHub

I was a bit disappointed by lack of stability of both Exq and Toniq under very heavy workloads so I’ve written pure OTP lib.

Waiting for comments!

Showing Posts 1 to 10

sztosz

sztosz

I just read readme, and in one part you call queues SampleApp.QueueHeavy and SampleApp.QueueLight and in other SampleApp.Queue.Heavy and SampleApp.Queue.Light notice the additional dot after Queue Is it simply different naming without any consequences, or is there more to it?

alisinabh

alisinabh

Awesome!

michalmuskala

michalmuskala

One thing that bothers me is the requirement to have a module that implements the perform function. Why now allow the user to pass module, function, args - just like in a task, instead? This would make it much more generic, and allow using with functions that weren’t implemented with this library in mind.

mspanc

mspanc OP

Membrane Core Team

I think I just made a typo.

mspanc

mspanc OP

Membrane Core Team

Nice suggestion! I’ll change this in the future release.

abitdodgy

abitdodgy

@mspanc I was having a look at the docs and something made me curious (I have little knowledge of job queue libs, so don’t mind me if this sounds naive): Without persistence, what happens if the machine goes down? Don’t you lose any enqueued jobs? It seems to me that any queueing library that has to do business critical work, should have a persistence mechanism, no?

hubertlepicki

hubertlepicki

That is a big assumption that all the stuff in queue is business-critical. In my experience, for a lot of system, background queue is where you push stuff like sending e-email, generating thumbnails etc. etc.

Sending e-mails probably the most common case and even in simple systems you want to push it to the background queue. And this can fail for other reasons too, so is not reliable by definition.

There’s plenty of queue use cases that are more complicated but can do well without persistence.

fishcakez

fishcakez

Ecto Core Team

There are a few issues with the error handling.

The naive assumptions about the :DOWN reasons are incorrect in many situations. The simplest being a failed GenServer.call A library should not (because it can not) make assumptions about what happen based on the exit reason of a process. However we are able to format them with the Exception module that will get it right 99% of the time.

Note that it is possible for a generic user to call exit(:normal) which will mean that there will be a stopped gracefully but not a job ok log message. This will be treated as success but a task that calls exit(:normal) is treated a as failure because it did not return a response.

It is also possible for an async task to send a response but to exit abnormally - it is possible that the process receives an exit signal in between sending the response and exiting. Therefore when you receive a response you want to treat that as a successful job and demonitor with flush.

Calling Logger macros in a separate function is a poor pattern because information is lost. Meta data, such as the module, function and line, are included in the log event automatically. Moving the log messages to their own function loses the function and line information. It would also be more idiomatic to include custom metadata in the log messages than prefix them with the meta data..

The fault tolerance of a queue is not ideal and it somewhat breaks guarantees that the supervision (and queue) are trying to provide. A supervision tree intends that when a process exits in its tree that everything below it has been terminated or will exit asynchronously when it does (descendants are neighbours and not trapping exits). If a child is trapping exits then it may take “some time” to terminate because the exit signal is no propagated. This means that the child can still exist when the process is restarted because it is temporarily orphaned. Therefore if trapping exits in a child process the parent should also trap exits and terminate its child in its terminate callback. This guarantees that clean up occurs before the restart so that a restart is given a clean slate. Note with the current implementation that the Task.Supervisor is trapping exits and so during a restart the concurrency limit is not enforced.

I think in this situation a Queue should be a one_for_all supervisor because the Task.Supervisor needs to be started before the queue server can start any jobs, and the Task.Supervisor should be shutdown when the queue server exits. By providing a supervisor at the top of the libraries tree it also allows more freedom to make changes to supervision in the future. It is also follows OTP principles more closely and leaves error handling to a supervisor.

If there is a single job in the queue and it fails, it will be run X number of times and then be lost forever. I am unsure if the tight loop is desirable and whether their should be a user callback to handle a dropped job.

outlog

outlog

fyi, queued jobs are executed in random order, which was not expected by me at least.

Domain.Message
|> Domain.Repo.all
|> Enum.sort(&(&1.id > &2.id)) 
|> Enum.each(fn msg -> Jumbo.Queue.enqueue(Domain.Queue.Light, Domain.SampleSleepJob, [msg]) end)

defmodule Domain.SampleSleepJob do
  def perform(message) do
      :timer.sleep(1000)
      time = DateTime.utc_now
      IO.puts "#{time.hour}:#{time.minute}:#{time.second} - #{message.id}"
  end
end

if you run that with concurrency: 1 - execution of the queue is in rather random order..

mspanc

mspanc OP

Membrane Core Team

@abitdodgy At the moment the jobs are gone upon restart. I agree with further post of @hubertlepicki that assumption that good job is a persistent job is invalid. For example in most of the systems I make, due to their nature, you can rebuild the job queue from other data sources upon boot. Adding persistency mechanism as it works in Ruby’s Sidekiq or Exq/Toniq just adds some redundancy. Moreover, as @hubertlepicki stated, you often queue tasks that are non-critical anyway. However, if time will allow I will add some persistency mechanisms but they will be optional.

Where Next? Top

Trending in Announcing Top

woylie
Flop is an Elixir library that applies filtering, ordering and pagination parameters to your Ecto queries. offset-based pagination with...
New
MRdotB
I needed to reuse React components from my Chrome extension in my Phoenix/LiveView backend. I noticed that for Svelte/Vue, there are live...
New
woylie
I released Doggo, a collection of unstyled Phoenix components. https://github.com/woylie/doggo Features Unstyled Phoenix components....
New
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
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
anuaralfetahe
Hello Published a new library - ProcessHub! ProcessHub is a library designed to manage process distribution within the Elixir cluster. ...
New

Other Trending Topics Top

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
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New
AstonJ
This showed up on my feed.. anyone heard of it? Just hype? Ox Alpha is a reasoning model designed for coding, sustained ag...
New
bartblast
Hey folks, I just published a post about Hologram’s funding and where the project goes next - the short version: Curiosum as Main Spons...
New
CodeSync
:microphone: ElixirConf 2026 - Call for Talks is open! We’re heading to Chicago :united_states: :round_pushpin: In person + virtual :d...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews