1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
//! Defines the executable side of a supervised task.
//!
//! [`Task`] is a factory for attempt futures. Application code usually creates one with [`TaskFn`](crate::TaskFn),
//! or implements the trait for a named type. [`TaskRef`] erases that concrete type for [`TaskSpec`](crate::TaskSpec).
//! After admission, Taskvisor calls [`Task::spawn`] once for each attempt and polls the returned [`BoxTaskFuture`].
//!
//! ```text
//! application task ──► TaskRef ──► TaskSpec ──► registry admission
//! ▼
//! TaskActor
//! ▼
//! run_once
//! ▼
//! Task::spawn(TaskContext) ──► BoxTaskFuture
//! ```
use ;
use crateTaskError;
use crateTaskContext;
/// Type-erased future for one task attempt.
///
/// [`Task::spawn`] returns this future for the attempt runner to poll.
pub type BoxTaskFuture = ;
/// Shared, type-erased [`Task`] handle used by [`TaskSpec`](crate::TaskSpec).
pub type TaskRef = ;
/// A factory for supervised attempt futures.
///
/// Task identity belongs to [`TaskSpec`](crate::TaskSpec), not to the executable object.
/// The same [`TaskRef`] can be registered through different specs.
/// Separate registrations may call [`spawn`](Task::spawn) concurrently on that shared object.
///
/// # Attempt contract
///
/// The actor reuses the task object. Its attempt runner calls [`spawn`](Task::spawn) once per attempt.
/// Each call must return a new future. Fields in the task object may keep state across retries;
/// values owned by the returned future belong only to that attempt.
///
/// ```text
/// Task object
/// ├── spawn(ctx) ────────► attempt 1
/// └── later spawn(ctx) ──► attempt 2
/// ```
///
/// # Implementing a named task
///
/// ```rust
/// use taskvisor::{BoxTaskFuture, Task, TaskContext, TaskError};
///
/// struct Worker;
///
/// impl Task for Worker {
/// fn spawn(&self, ctx: TaskContext) -> BoxTaskFuture {
/// Box::pin(async move {
/// ctx.cancelled().await;
/// Err(TaskError::Canceled)
/// })
/// }
/// }
/// ```
///
/// # Cancellation
///
/// Long-running tasks must observe [`TaskContext`] and return [`TaskError::Canceled`] after a cooperative stop.
/// Cancellation is never retried. A task that does not stop within the removal or shutdown grace window may be aborted.
/// Timeout drops the future inside the attempt runner. Abort asks Tokio to drop it after the current poll returns.
/// Neither action rolls back external side effects or interrupts synchronous code inside a poll.
///
/// Taskvisor drops every attempt future synchronously on its Tokio worker. Keep destructors for future-owned values
/// short and non-blocking. A blocking destructor delays attempt release and holds any concurrency permit until it returns.
///
/// # Attempt results
///
/// | Result | Actor decision |
/// |-------------------------|-----------------------------------------------------|
/// | `Ok(())` | Repeat only under `RestartPolicy::Always` |
/// | [`TaskError::Fail`] | Retry when policy and retry limit allow it |
/// | [`TaskError::Timeout`] | Retry when policy and retry limit allow it |
/// | [`TaskError::Canceled`] | Stop |
/// | [`TaskError::Fatal`] | Stop |
///
/// A primary panic while creating or polling the future is classified as [`TaskError::Fail`].
/// A cleanup panic while dropping user-owned attempt data stops normal retry handling.
/// Do not use panic for expected failures.
///
/// # See also
///
/// - [`TaskFn`](crate::TaskFn) adapts an async closure.
/// - [`TaskSpec`](crate::TaskSpec) adds identity and execution settings.