sztosz

sztosz

Pooling and queue libraries in Elixir

Hi, I’ll be definitely needing a pooling in my next small project in work, because I don’t want to kill Elasticsearch cluster. And I was wondering what are the libraries out there to use? One of obvious choices is to simply use Poolboy, and from what I see it will fit my use case (cause it’s not that complicated). Should I even consider other libraries, and if which ones?

The other one is queues, I’ll need them too. The simplest queue I can think of is just process message-box, but I’ll probably want to persist those queues because I’ll probably would not like to loose them. And now the question is, what to use? I don’t want to use Redis or any other technology like this (because If I would need Redis, I can just install it and write logic in Python which would be faster given what I have already). Any one can suggest a good, minimal library with persistence layer? Bonus points for a lib that can synchronize it’s queues over at least two nodes (redundancy in case of a hardware failure, network problem etc.)

If you can even point me somewhere with some link I’d be grateful, because when I see that some libs where not updated in like 2 years, I’m simply not sure if they’re simply stable or just abandoned :wink:

Most Liked

sasajuric

sasajuric

Author of Elixir In Action

I’m not aware of an embedded solution for a distributed queue. I’d likely try RabbitMQ in that scenario.

However, if you want a local persistent queue with absolutely no external dependencies, then the solution would not be overly complex. I don’t know if there are libraries which do this out of the box, but rolling your own simple solution would IMO not be too complicated, and is at least a nice exercise of a bit of OTP :slight_smile:

The idea is to have an in-memory queue, and persist the queue state to disk every time an item is added, and every time the job succeeds.

Persisting without an external component can be done in a couple of ways:

In a simplest solution, you’d have one process, a GenServer, which would act as a scheduler. The scheduler reads from the queue file, and starts the first job in a separate process. If the job succeeds, the scheduler removes it, persists the new queue state, and starts the next job, if there is one. The scheduler should also monitor the job process (or link to it), to detect if it crashed. Then you need to handle the crash by retrying, deferring the job, giving up.

Every time you want to add another item, you send a request to the scheduler, which adds it to the end of the in memory structure (for example :queue), stores to disk, and starts the job if nothing is running.

I’d suggest to try rolling a simple implementation, perhaps starting with a plain in-memory queue, and then adding naive persistence with File.write(:erlang.term_to_binary(queue)).

If you have more elaborate needs, such as pooled or rate-limited queues, you could take a look at jobs. I’m actually using it myself for these particular cases, and I’m quite happy with it.

cjbottaro

cjbottaro

The author of Sidekiq has a new project for async work queues called Faktory which is language agnostic and addresses some of the main design short comings of Sidekiq.

There is a fully featured Elixir client for it that is actively being developed:
https://hexdocs.pm/faktory_worker_ex

:v:

sasajuric

sasajuric

Author of Elixir In Action

I don’t know of any. But you don’t need a wrapper, you can use jobs directly. The examples in Erlang are here, and the comparison of syntax differences can be found here. So e.g. if we take this example:

jobs:add_queue(q, [{standard_rate,1}]).
...
jobs:run(q, fun() -> io:fwrite("job: ~p~n", [time()]) end).

It could be roughly translated as e.g.:

:jobs.add_queue(:q, [standard_rate: 1])
...
:jobs.run(:q, fn -> IO.inspect(DateTime.utc_now()) end)

More generally, to use jobs, you need to first create a named queue with :jobs.add_queue(queue_name, opts), where queue_name is an atom. Typically this can be done in the application start callback.

Then you can run a queued operation from any process as :jobs.run(queue_name, fn -> ... end).

Take a look ad add_queue docs, in especially the “regulators” section. To create a rate-limited queue, you can pass rate: [...]. To create a counter queue (limit max simultaneous jobs), you can pass counter: [...].

Where Next?

Popular in Questions Top

freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
LegitStack
I’m hoping you guys can give me some general advice and perhaps code examples if you’re feeling up to it. I’m very interested in Elixir,...
New
sacepums
Hey guys. I'm new to elixir and im really stocked about it. But I ran into a bit of problem - I need to convert a date sting, for examp...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
makeitrein
Hey all, just started picking up Elixir last week and am writing a scraper as a learning project. Baby step #1 is extracting the number ...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
idi527
I’ve been re-reading swift book again and noticed that multiline strings there don’t have a trailing line break, unlike in elixir iex(2)...
New

Other popular topics Top

peerreynders
Manning 2016 Halloween weekend sale via Deal of the Day Friday, October 28 - Half off all MEAPs - code WM102816LT Saturday, October 29 ...
326 29600 154
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
sacepums
Hey guys. I'm new to elixir and im really stocked about it. But I ran into a bit of problem - I need to convert a date sting, for examp...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 42633 214
New
AstonJ
by Lance Halvorsen Elixir and Phoenix are generating tremendous excitement as an unbeatable platform for building modern web application...
460 27162 124
New

We're in Beta

About us Mission Statement