#task-manager #tokio-task #group #nested #opinionated #outcome #generic

task-motel

Opinionated (Tokio) task manager with nested task groups and stoppable tasks

5 releases

0.1.0 Oct 4, 2023
0.1.0-rc.3 Jan 20, 2023
0.1.0-rc.1 Jan 17, 2023
0.1.0-rc.0 Jan 13, 2023

#3 in #outcome

Download history 288/week @ 2023-12-07 273/week @ 2023-12-14 113/week @ 2023-12-21 71/week @ 2023-12-28 187/week @ 2024-01-04 330/week @ 2024-01-11 344/week @ 2024-01-18 361/week @ 2024-01-25 592/week @ 2024-02-01 226/week @ 2024-02-08 328/week @ 2024-02-15 225/week @ 2024-02-22 517/week @ 2024-02-29 371/week @ 2024-03-07 381/week @ 2024-03-14 497/week @ 2024-03-21

1,826 downloads per month
Used in 7 crates (via holochain)

Apache-2.0

24KB
519 lines

task-motel

An opinionated Tokio* task manager with arbitrary nested groupings of tasks.

The task manager takes two generic parameters:

pub struct TaskManager<GroupKey, Outcome>
where
    GroupKey: Clone + Eq + Hash + Send + std::fmt::Debug + 'static,
    Outcome: Send + 'static,

Each distinct GroupKey (as defined by Eq) corresponds to a distinct group, so tasks registered with the same GroupKey are in the same group. It is useful to use an enum for your GroupKey.

The Outcome is the type that all tasks must return, which may be whatever you want.

* task-motel is built to be almost entirely executor-agnostic, but ultimately I needed the ability to spawn a task which would run to completion without polling, which I could not find without leaning on some executor or another. If this can be solved, then the Tokio dependency can be removed.

Handling task outcomes

When constructing a TaskManager, you are given a channel receiver, which receives (GroupKey, Outcome) for each task that has completed. Depending on the outcome of a task, you may respond by terminating the application, logging an error, spawning new tasks, or whatever else you want.

Grouped tasks

When registering a task, you assign it to a group. That group of tasks can be managed separately from other groups of tasks: the entire group can be instructed to stop, and the shutdown can be awaited.

Nested groups

Groups can be arbitrarily nested, so that shutting down a parent group will also shut down all child groups recursively. The nesting structure is determined by Fn(GroupKey) -> Option<GroupKey> function argument to the TaskManager::new constructor, which takes a GroupKey and produces an Option<GroupKey> declaring the parent of the group, defining the tree structure.

Stopping tasks

When registering a task, you must do so with a closure that gets a StopListener injected into it. This StopListener is a simple future which is resolved when the task manager receives a shutdown signal, so it should be incorporated into your task accordingly, to allow the task to shut down from external input.

The StopListener should be dropped only after the task is complete, because the task manager uses the number of StopListeners in circulation to determine how many tasks are being actively managed.

Dependencies

~3–11MB
~77K SLoC