tokio-interval-set
A lightweight Rust utility for running a closure repeatedly on a fixed time
interval, backed by tokio's time and task system.
tokio-interval-set provides a simple, safe, and ergonomic API for launching
periodic background tasks — think JavaScript's setInterval, but for async
Rust with cancellation handled via a dedicated handle.
Features
- ⏱️ Fixed-interval execution — Run any async closure on a repeating
tokio::time::Interval. - 🛑 Graceful cancellation — Call
clear()on the returned handle to synchronously stop the loop after the current tick completes. - 🔄 Drop-safe — Dropping the handle (without calling
clear()) also stops the task on the next tick boundary; nothing leaks. - 🚨 Panic detection — If the spawned task panics, calling
clear()will panic with a descriptive message so you know something went wrong. - 🪶 Minimal — One function, one struct, zero dependencies beyond
tokio.
Quick Start
Add the crate to your Cargo.toml:
[]
= "0.1.0"
= { = "1", = ["time", "sync", "rt", "macros"] }
Then use it in your code:
use Arc;
use Duration;
use Mutex;
use interval;
use set_interval;
let rt = new_current_thread
.enable_time
.build
.unwrap;
rt.block_on;
API Overview
set_interval(interval, func) -> IntervalHandle
Spawns a background task that calls func() every time the given
tokio::time::Interval ticks.
| Parameter | Type | Description |
|---|---|---|
interval |
tokio::time::Interval |
Controls the tick timing. |
func |
Fn() -> Fut + Send + Sync + 'static |
Closure returning a future. |
IntervalHandle
The handle returned by set_interval. It exposes one method:
| Method | Description |
|---|---|
clear(self) |
Synchronously stops the interval loop. Panics if the task has panicked. |
If the handle is dropped without calling clear(), the interval task is
cancelled on the next tick boundary.
Examples
Stopping via clear()
use Arc;
use Duration;
use Mutex;
use interval;
use set_interval;
let rt = new_current_thread
.enable_time
.build
.unwrap;
rt.block_on;
Dropping the handle (automatic cancellation)
use Arc;
use Duration;
use Mutex;
use interval;
use set_interval;
let rt = new_current_thread
.enable_time
.build
.unwrap;
rt.block_on;
How It Works
set_intervalcreates atokio::sync::oneshotchannel and spawns a background task viatokio::spawn.- The task loops, using
tokio::select!to wait on both the [Interval] tick and a shutdown signal from the oneshot receiver. - On each tick, the closure is called and awaited.
- When
clear()is invoked (or the handle is dropped), the oneshot sender is consumed / dropped, the receiver wakes up, and the loop exits.
This approach ensures that:
- The interval task runs concurrently with your other async work.
- The current tick's closure completes before the loop exits.
- No busy-waiting or manual thread management.
Safety & Correctness
- No
unsafecode — the crate is written entirely in safe Rust. - Cancellation is clean — the shutdown signal is sent via a oneshot channel; the loop exits on the next iteration.
- Panic propagation — if the closure panics, the spawned task panics and
the oneshot receiver is dropped. Calling
clear()on a panicked task produces a clear panic message ("Interval was panic"), so the error is never silently swallowed.
License
This project is licensed under the MIT License.