Summary
Replace the public API exposure of tokio_util::sync::CancellationToken with a runtime-agnostic abstraction.
Motivation
Currently, ActivityContext exposes tokio_util::sync::CancellationToken in its public API:
pub fn cancellation_token(&self) -> tokio_util::sync::CancellationToken
While most users can avoid importing this type (using ctx.is_cancelled() or ctx.cancelled() instead), the type is still part of the public API surface.
Reasons to abstract:
- May want to switch to a lighter weight async runtime in the future
- Enable a minified version of duroxide for resource-constrained environments
- Reduce coupling to tokio ecosystem in public API
Current Public API Surface (tokio-dependent)
| Method |
Returns |
Tokio Dependency |
ctx.is_cancelled() |
bool |
None (uses token internally) |
ctx.cancelled() |
impl Future |
None (wraps token) |
ctx.cancellation_token() |
tokio_util::sync::CancellationToken |
Direct exposure |
Proposed Solutions
Option A: Define a trait abstraction
pub trait CancellationSignal: Clone + Send + Sync {
fn is_cancelled(&self) -> bool;
fn cancelled(&self) -> impl Future<Output = ()> + Send;
}
Option B: Use async_channel internally (runtime-agnostic)
// Channel close = cancellation signal
let (sender, receiver) = async_channel::bounded(1);
sender.close(); // Signal cancellation
receiver.recv().await; // Wait for cancellation
Option C: Custom implementation with atomics + wakers (no external deps)
Non-Goals
- This issue does NOT propose removing tokio from the runtime internals (that would be a much larger effort)
- This is specifically about the public API surface
Impact
- Low priority - current implementation works well
- Most users do not need to import
CancellationToken directly
- Breaking change if we modify
cancellation_token() return type
Summary
Replace the public API exposure of
tokio_util::sync::CancellationTokenwith a runtime-agnostic abstraction.Motivation
Currently,
ActivityContextexposestokio_util::sync::CancellationTokenin its public API:While most users can avoid importing this type (using
ctx.is_cancelled()orctx.cancelled()instead), the type is still part of the public API surface.Reasons to abstract:
Current Public API Surface (tokio-dependent)
ctx.is_cancelled()boolctx.cancelled()impl Futurectx.cancellation_token()tokio_util::sync::CancellationTokenProposed Solutions
Option A: Define a trait abstraction
Option B: Use
async_channelinternally (runtime-agnostic)Option C: Custom implementation with atomics + wakers (no external deps)
Non-Goals
Impact
CancellationTokendirectlycancellation_token()return type