diff --git a/docs/glossary.md b/docs/glossary.md index 62bdab6..64dff50 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -30,7 +30,7 @@ Quick reference for terms used throughout the taskmill documentation. | **Recurring task** | A task that automatically re-submits itself after each completion according to a `RecurringSchedule`. Recurring schedules survive restarts and support pause, resume, and cancel operations. See [Quick Start](quick-start.md#recurring-tasks). | | **Typed task** | A struct that implements the `TypedTask` trait, giving you compile-time type safety for task payloads and configuration. Declares `type Domain: DomainKey` for compile-time domain identity and `fn config() -> TaskTypeConfig` for static defaults (priority, IO budget, TTL, retry policy, etc.). Register with `Domain::task::(executor)` and submit with `handle.submit(task)`. See [Quick Start](quick-start.md#typed-tasks). | | **TaskTypeConfig** | A struct returned by `TypedTask::config()` that holds static per-task-type defaults — priority, IO budget, group key, TTL, retry policy, duplicate strategy, etc. All fields are `Option`; `None` means "use the next layer's default" (domain default, then scheduler global, then built-in). | -| **DomainSubmitBuilder** | The fluent builder returned by `DomainHandle::submit_with(task)`. Implements `IntoFuture` so bare `.await` applies all defaults; chain override methods (`.priority()`, `.run_after()`, `.parent()`, etc.) before `.await` to override individual fields for that call only. | +| **DomainSubmitBuilder** | The fluent builder returned by `DomainHandle::submit_with(task)`. Implements `IntoFuture` so bare `.await` applies all defaults; chain override methods (`.priority()`, `.run_after()`, `.parent()`, `.fail_fast()`, etc.) before `.await` to override individual fields for that call only. | | **Domain-scoped state** | Application state registered on a `Domain` via `.state(value)`, visible only to executors within that domain. `TaskContext::state::()` checks domain state first and falls back to global state registered on `SchedulerBuilder`. See [Configuration](configuration.md#application-state). | | **TypedEventStream** | A per-task-type event subscription (`TypedEventStream`) created via `handle.task_events::()`. Filters the global scheduler event broadcast to only events matching `T::TASK_TYPE` within the domain. Terminal events include the `TaskHistoryRecord`. | | **Qualified task type** | The full database-stored task type including the domain prefix, e.g. `"media::thumbnail"`. Required when using store-level query APIs (`history_stats`, `task_lookup`, `avg_throughput`). `DomainHandle` methods apply the prefix automatically, so you typically only need the short form when submitting tasks. | diff --git a/docs/quick-start.md b/docs/quick-start.md index 566f022..8e2b679 100644 --- a/docs/quick-start.md +++ b/docs/quick-start.md @@ -294,7 +294,20 @@ ctx.domain::() .await?; ``` -By default, if any child fails, its siblings are cancelled and the parent fails immediately (fail-fast). Disable this per-submission with `.fail_fast(false)`. +By default, if any child fails, its siblings are cancelled and the parent fails immediately (fail-fast). Disable this per-submission with `.fail_fast(false)`: + +```rust +// Typed builder +media.submit_with(ScanTask { .. }) + .fail_fast(false) + .await?; + +// Untyped +scheduler.submit( + TaskSubmission::new("scan") + .fail_fast(false) +).await?; +``` ## Sharing the scheduler diff --git a/src/domain.rs b/src/domain.rs index 3c5c6ba..7b351fa 100644 --- a/src/domain.rs +++ b/src/domain.rs @@ -861,6 +861,15 @@ impl DomainSubmitBuilder { self } + /// Control whether a child failure immediately fails the parent. + /// + /// Defaults to `true`. Set to `false` to let the parent's `finalize()` + /// run even when some children fail. + pub fn fail_fast(mut self, fail_fast: bool) -> Self { + self.inner = self.inner.fail_fast(fail_fast); + self + } + /// Set the parent task ID. pub fn parent(mut self, id: i64) -> Self { self.inner = self.inner.parent(id); diff --git a/src/lib.rs b/src/lib.rs index 49f1bf2..45756cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -127,7 +127,9 @@ //! [`TypedExecutor::finalize`] method is called — useful for assembly work //! like `CompleteMultipartUpload`. If any child fails and //! [`fail_fast`](TaskSubmission::fail_fast) is `true` (the default), siblings -//! are cancelled and the parent fails immediately. +//! are cancelled and the parent fails immediately. Disable this with +//! [`DomainSubmitBuilder::fail_fast(false)`](DomainSubmitBuilder::fail_fast) +//! (or [`TaskSubmission::fail_fast`] for untyped submissions). //! //! ## Task TTL & automatic expiry //! diff --git a/src/task/submit_builder.rs b/src/task/submit_builder.rs index b5c1ec9..1617f92 100644 --- a/src/task/submit_builder.rs +++ b/src/task/submit_builder.rs @@ -112,6 +112,7 @@ pub struct SubmitBuilder { override_on_dependency_failure: Option, override_tags: HashMap, override_parent_id: Option, + override_fail_fast: Option, } impl SubmitBuilder { @@ -140,6 +141,7 @@ impl SubmitBuilder { override_on_dependency_failure: None, override_tags: HashMap::new(), override_parent_id: None, + override_fail_fast: None, } } @@ -212,6 +214,15 @@ impl SubmitBuilder { self } + /// Control whether a child failure immediately fails the parent. + /// + /// Defaults to `true`. Set to `false` to let the parent's `finalize()` + /// run even when some children fail. + pub fn fail_fast(mut self, fail_fast: bool) -> Self { + self.override_fail_fast = Some(fail_fast); + self + } + /// Set the parent task ID for hierarchical tasks (parent-child /// relationship). This does **not** establish a dependency — use /// [`depends_on`](Self::depends_on) for that. @@ -349,6 +360,9 @@ impl SubmitBuilder { if let Some(pid) = self.override_parent_id.take() { self.submission.parent_id = Some(pid); } + if let Some(ff) = self.override_fail_fast.take() { + self.submission.fail_fast = ff; + } } /// Submit the task, returning the outcome.