2 unstable releases
new 0.1.0 | Dec 16, 2024 |
---|---|
0.0.1-dev | Dec 6, 2024 |
#217 in Concurrency
235 downloads per month
37KB
679 lines
Sprinter 👟
A Rust library for running parallel queued tasks with controlled concurrency.
Features
- ⚡ Run tasks in parallel with configurable concurrency limits
- 🔄 Queue tasks and manage their execution
- 📊 Track task states (Pending, Running, Succeed, Failed)
- 🚦 Control task flow with push/wait mechanisms
- 🔍 Monitor individual task completion and results
Installation
Add this to your Cargo.toml
:
[dependencies]
sprinter = "0.0.1-dev"
Usage
Basic Example
Here's a basic example of using Sprinter to run parallel tasks:
use sprinter::Queue;
use std::fmt::Error;
use tokio::time::sleep;
#[tokio::main]
async fn main() {
println!("sprint start ...");
let start = tokio::time::Instant::now();
// Create a queue with concurrency of 2 and tick interval of 50ms
let queue: Queue<i32, Error> = Queue::new(2, 50);
// Define some async tasks
let task1 = || async {
println!("task1 start ...");
sleep(tokio::time::Duration::from_millis(250)).await;
println!("task1 done!");
Ok(1)
};
let task2 = || async {
println!("task2 start ...");
sleep(tokio::time::Duration::from_millis(50)).await;
println!("task2 done!");
Ok(2)
};
let task3 = || async {
println!("task3 start ...");
sleep(tokio::time::Duration::from_millis(50)).await;
println!("task3 done!");
Ok(3)
};
// Push tasks to the queue
queue.push(&"task1".to_string(), task1).await.unwrap();
queue.push(&"task2".to_string(), task2).await.unwrap();
queue.push(&"task3".to_string(), task3).await.unwrap();
// Signal that all tasks have been pushed
queue.set_push_done().await;
// Wait for all tasks to complete and get results
let results = queue.wait_for_tasks_done().await;
let end = tokio::time::Instant::now();
println!("sprint done in {:?}", end - start);
println!("results: {:?}", results);
}
It will print:
sprint start ...
task1 start ...
task2 start ...
task2 done!
task3 start ...
task3 done!
task1 done!
sprint done in 251.949651ms
results: {"task1": Ok(Ok(1)), "task2": Ok(Ok(2)), "task3": Ok(Ok(3))}
This will execute tasks in parallel with a maximum concurrency of 2, meaning two tasks can run simultaneously. The output will show tasks running and completing based on their duration and the concurrency limit.
API
Creating a Queue
let queue: Queue<T, E> = Queue::new(concurrency: usize, tick_interval: u64);
concurrency
: Maximum number of tasks that can run in paralleltick_interval
: Interval in milliseconds between queue processing ticksT
: Type of successful task resultE
: Type of task error
Methods
push
async fn push<F, R>(&self, task_id: &String, task: F) -> Result<(), QueueError>
where
F: FnOnce() -> R + Send + 'static,
R: Future<Output = Result<T, E>> + Send + 'static
Pushes a new task to the queue, it will be executed as soon as it is pushed or when the queue is ready. Each task must have a unique ID, tasks execution is deduped by task_id.
set_push_done
async fn set_push_done(&self)
Signals that all tasks have been pushed to the queue. Note the queue will not complete until set_push_done
is called, even if all tasks have been completed.
task_done
async fn task_done(&self, task_id: &String) -> Result<Result<T, E>, QueueError>
Waits for a specific task to complete and returns its result.
wait_for_tasks_done
async fn wait_for_tasks_done(&self) -> HashMap<String, Result<Result<T, E>, QueueError>>
Waits for all tasks to complete and returns a map of task IDs to their results. set_push_done
must be called before this method.
reset
async fn reset(&self)
Resets the queue to its initial state, clearing all tasks and results.
Task States
Tasks can be in one of these states:
Pending
: Task is queued but not yet runningRunning
: Task is currently executingSucceed
: Task completed successfullyFailed
: Task failed with an error
License
This project is licensed under the MIT License - see the LICENSE file for details.
Dependencies
~2.6–8.5MB
~74K SLoC