#[timer_task]Expand description
Apply to the TimerTask trait definition, an
impl TimerTask<S [, K]> for T block, or — for less boilerplate — an
inherent impl T { ... } block.
Use as #[cano::task::timer].
Two surface forms on impl blocks:
- Trait-impl form:
#[task::timer] impl TimerTask<S> for T { async fn wait(..) { ... } async fn after_wait(..) { ... } }— user writes the trait header. The macro async-rewrites theTimerTaskimpl AND emits a companionimpl Task<S> for TwhoseTask::runsleeps for the returnedTimerOutcome(via therun_timerhelper) then callsafter_wait. - Inherent-impl form:
#[task::timer(state = S [, key = K])] impl T { async fn wait(..) { ... } async fn after_wait(..) { ... } }— the macro builds theimpl TimerTask<S [, K]> for Theader from the attribute args, enforces that bothwaitandafter_waitare present (config/namemay be overridden), and emits the same companionimpl Task<S [, K]> for T.
On a trait definition (#[task::timer] pub trait TimerTask ...) the macro just performs the
async-fn-in-trait rewrite.
Because a blanket impl<T: TimerTask<..>> Task<..> for T would conflict (E0119) with the
analogous blanket impls for the other specialized task traits — a type can implement more than
one — the companion Task impl is generated per-use-site rather than as a blanket.
The default config() injected by the inherent form is [TaskConfig::minimal()]
(no retries) — a single scheduled sleep needs no outer retry wrapping.
The inherent form routes Task::run through ::cano::task::timer::run_timer, so the user
crate needs no direct tokio dependency. The trait-impl form inlines the sleep, so a crate
using #[task::timer] impl TimerTask<S> for T must depend on tokio (feature time),
reachable as ::tokio — the same requirement the sibling #[task::poll] macro has.