# Is there a way to keep and manage an parallel/asyncronous task queue?

**URL:** <https://discourse.julialang.org/t/is-there-a-way-to-keep-and-manage-an-parallel-asyncronous-task-queue/53942>\
**Category:** General Usage\
**Tags:** parallel, multithreading, distributed, actors\
**Created:** [January 25, 2021, 11:31pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-keep-and-manage-an-parallel-asyncronous-task-queue/53942 "2021-01-25T23:31:50Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![apoor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/apoor/32/21367_2.png) [@apoor](https://discourse.julialang.org/u/apoor)\
**Post date:** [January 25, 2021, 11:31pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-keep-and-manage-an-parallel-asyncronous-task-queue/53942/1 "2021-01-25T23:31:50Z")

</div>

I’m playing around with writing a simple load tester (sort of like [locust](https://locust.io/)). I want to maintain a task-queue/pool of workers making requests to my web app.

When the program starts, the worker pool will fill up. As some requests finish, more requests are added until the user stops it.

I’ve looked through the documentation for [base/parallel](https://docs.julialang.org/en/v1.5/base/parallel/) and read a bit about `Tasks`, `@async`, and `Channels`, but it seems like they mostly have to do with definite loops rather than indefinite loops.

Can you suggest a different way to go about doing this or another library I should try?

Thanks in advance!

---

<div class="post-metadata">

**Author:** ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)\
**Post date:** [January 26, 2021, 7:14am UTC](https://discourse.julialang.org/t/is-there-a-way-to-keep-and-manage-an-parallel-asyncronous-task-queue/53942/2 "2021-01-26T07:14:52Z")

</div>

Welcome! Sounds a lot of what @tisztamo does with lightweight actors:

> **[GitHub - Circo-dev/Circo: A fast and scalable actor system in Julia](https://github.com/Circo-dev/Circo)**
>
> A fast and scalable actor system in Julia. Contribute to Circo-dev/Circo development by creating an account on GitHub.

or maybe also

> **[GitHub - JuliaActors/QuickActors.jl: Reference implementation for...](https://github.com/JuliaActors/QuickActors.jl)**
>
> Reference implementation for ActorInterfaces.Classic - GitHub - JuliaActors/QuickActors.jl: Reference implementation for ActorInterfaces.Classic

> [@apoor](#):
>
> Tasks … they mostly have to do with definite loops rather than indefinite loops

Tasks in Julia can start other tasks (with `@async` or `@spawn`). They are lightweight. You can give arguments to their functions or send them messages via channels. Thus there is no practical limitation for iterations they can do.

---

<div class="post-metadata">

**Author:** ![tisztamo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tisztamo/32/16200_2.png) [@tisztamo](https://discourse.julialang.org/u/tisztamo)\
**Post date:** [January 26, 2021, 10:06am UTC](https://discourse.julialang.org/t/is-there-a-way-to-keep-and-manage-an-parallel-asyncronous-task-queue/53942/3 "2021-01-26T10:06:18Z")

</div>

If I understand correctly, your plan is to create a central scheduler that selects the next action for every idle “user” and dispatches the work of sending out requests (running the function that is called a `@task` in Locust.) to the worker pool. Is that correct?

This seems possible with Julia tasks, e.g. a very simple implementation could be that you create a single channel which is filled by the scheduler with Locust-like `@task`s, and all the (idle) workers (Julia tasks) are reading from it at the other end. After reading the Locust-like `@task` descriptor, the worker runs it, notifies the scheduler using another channel, and goes back to reading. The scheduler then selects a new Locust `@task` for that user. The number of workers can be much higher than the number of threads, and the Julia task scheduler will do the work of distributing the load between the tasks, so this should work and use more or less all the resources of a single machine. But the central scheduler can become a bottleneck, especially when you later want to move to distributed processing.

Another possibility is to model every user with its own Julia task, or even use an actor model, where every user is an actor. This will get you better scalability and possibly nicer code. E.g. Circo promises to auto-balance actors between distributed nodes during runtime, but it is not yet really usable and documented. For quick results I would suggest trying out [Actors.jl](https://github.com/JuliaActors/Actors.jl).

Note that I am looking for a use case to create a sample showing how to use Circo in real life (sort of a reference application), and I find this one a real fit. Please PM me if you are interested in working together!
