fabianlindfors

fabianlindfors

ParallelTask: easily run functions in parallel and capture the results

Hi!

ParallelTask on Github

I’m quite new to the Elixir community and so far hooked on the language and ecosystem. Today I read a nice article by Ryan Sydnor on how they speed up their application by parallelising database queries. He used tasks to concurrently run the expensive queries which improved performance drastically. The full article can be read here.

Elixir really shines in cases like these and I thought it would be great to have a library for simple parallelization. That’s why I created ParallelTask, a lightweight wrapper around Task making it easy to parallelize API requests, database queries, and the like.

This is my first Elixir project and any feedback is much welcomed. Thanks!

Most Liked

axelson

axelson

Scenic Core Team

I like the idea, how you can build up the tasks to execute in parallel and then execute them together. Although since the idea is conceptually very similar to Ecto.Multi I think it would make sense to mirror that API.

So instead of:

|> ParallelTask.add(first_task: fn -> "Result from first task" end)

We could write:

|> ParallelTask.add(:first_task, fn -> "Result from first task" end)

That would also allow us to more flexibly name our tasks (Ecto.Multi actually now accepts strings)

jaimeiniesta

jaimeiniesta

I like it, it reads nicely!

mbuhot

mbuhot

Nice package! :thumbsup:

It’s surprising that the Task module doesn’t make it easier to work with keyed tasks like this.
The closest I could get without writing a helper function is:

tasks = %{a: async(fn -> "foo" end), b: async(fn -> "bar" end)}
results = for {k, v} <- tasks, into: %{}, do: {k, Task.await(v)}

But that has slightly different semantics to your package (starts tasks eagerly and awaits each separately).

The implementation of add can benefit from some pattern matching and map update syntax:

def add(%__MODULE__{task_functions: task_functions} = object, new_functions \\ []) do
  %{object | task_functions: Enum.into(task_functions, new_functions)}
end

I try not to use Enum.at wherever possible, such as in the definition of perform, I’d try to use unzip and zip to match the keys and results together:

def perform(%__MODULE__{task_functions: task_functions}, timeout \\ 5000) do
    {keys, tasks} =
      task_functions
      |> Enum.map(fn {k, f} -> {k, Task.async(f)} end)
      |> Enum.unzip()

    task_results =
      tasks
      |> Task.yield_many(timeout)
      |> Enum.map(&get_task_result/1)

    keys
    |> Enum.zip(task_results)
    |> Map.new()
  end

Where Next?

Popular in Announcing Top

OvermindDL1
I created a new library (rather I pulled out a couple files from my big project), it manages an operating system PID file for the BEAM. ...
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 43487 311
New
pkrawat1
Presenting Aviacommerce, open source e-commerce platform in Elixir Aviacommerce is an open source e-commerce platform in Elixir. We at...
New
mbuhot
Leverage Open Api 3.0 (Swagger) to document, test, validate and explore your Plug and Phoenix APIs. Generate and serve a JSON Open API ...
New
Azolo
Hey everyone, I just released WebSockex which is a Elixir WebSocket client. WebSockex strives to work as a OTP special process, be RFC6...
New
Jskalc
Hi! Today, after a couple weeks of development I’ve released v0.1 of LiveVue. It’s a seamless integration of Vue and Phoenix LiveView, i...
New
hpopp
After just over two years in development, this latest version of Pigeon is what I finally consider done in regards to my original vision ...
New
achempion
Hi, I would like to tell about my initiative to further maintain and develop Waffle project which is the fork of Arc library. The progre...
New
michalmuskala
Hello everybody. I have just released Jason - a new JSON library. You might be wondering, why do we need a new library? The primary foc...
New
kevinlang
Hey all, We have made an Ecto3 Adapter for SQLite3, ecto_sqlite3! We have successfully on-boarded the full suite of integration tests (...
New

Other popular topics Top

axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 48342 226
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31013 112
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
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
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
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
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54120 245
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New

We're in Beta

About us Mission Statement