docs: document custom type support throughout project
Update all documentation to reflect that custom types work automatically with the #[task] macro, requiring only Clone + Send + Sync + 'static. Documentation updates: - README: Add custom types to features, new Custom Types section - CHANGELOG: Document custom type improvement in [Unreleased] - src/lib.rs: Add custom types example to main API docs - src/task.rs: Update Task trait docs to mention macro-generated extraction - src/extract.rs: Clarify ExtractInput is now internal-only (for task_fn) - dagx-macros: Update macro docs to emphasize automatic type handling New example: - examples/custom_types.rs: Simple 120-line example showing User type flowing through DAG with fan-out pattern (one output → two consumers) demonstrating Arc wrapping is automatic and transparent This makes the custom type capability discoverable and prominent for users, turning a previous limitation into a headline feature.
This commit is contained in:
8 files changed
+366
-7
No files matched your search
+18
-5
@@ -1,15 +1,28 @@
|
||||
//! Input extraction for task dependencies via oneshot channels.
|
||||
//!
|
||||
//! This module handles extracting typed inputs from task dependencies via oneshot channels.
|
||||
//! # Legacy Trait for Internal Use Only
|
||||
//!
|
||||
//! **NOTE**: This module is now primarily for internal use. The `ExtractInput` trait is only
|
||||
//! used by the internal `task_fn` test helper function.
|
||||
//!
|
||||
//! **For regular tasks**: The `#[task]` macro generates inline `extract_and_run()` methods with
|
||||
//! type-specific extraction logic. This means **ANY type** implementing `Clone + Send + Sync`
|
||||
//! works automatically without needing `ExtractInput` implementations!
|
||||
//!
|
||||
//! # How it works
|
||||
//!
|
||||
//! When a task executes, it needs to extract its inputs from type-erased oneshot receivers.
|
||||
//! Outputs are wrapped in Arc for efficient fanout (cheap Arc clones instead of data clones).
|
||||
//! This module provides the ExtractInput trait with implementations for:
|
||||
//! - `()` for tasks with no dependencies
|
||||
//! - Common types (`i32`, `String`, etc.) for tasks with a single dependency
|
||||
//! - `(A, B, ...)` tuples for tasks with multiple dependencies (awaited concurrently)
|
||||
//!
|
||||
//! **Modern approach (via `#[task]` macro)**:
|
||||
//! - The macro generates custom extraction logic inline in `extract_and_run()`
|
||||
//! - Works with ANY type (just needs `Clone + Send + Sync`)
|
||||
//! - No trait implementations needed!
|
||||
//!
|
||||
//! **Legacy approach (via `ExtractInput` trait)**:
|
||||
//! - Used only by the internal `task_fn` test helper
|
||||
//! - Provides implementations for primitives, standard types, and tuples
|
||||
//! - Requires explicit trait implementations for custom types (not recommended)
|
||||
//!
|
||||
//! # Why macros?
|
||||
//!
|
||||
|
||||
+50
@@ -10,6 +10,9 @@
|
||||
//! - **Compile-time type safety**: Dependencies are validated at compile time through the type
|
||||
//! system. The public API is fully type-safe with no runtime type errors. Internal execution
|
||||
//! uses type erasure for heterogeneous task storage, but this is never exposed to users.
|
||||
//! - **Works with ANY type**: Custom types work automatically with the `#[task]` macro—just
|
||||
//! implement `Clone + Send + Sync`, no trait implementations needed! The macro generates
|
||||
//! type-specific extraction logic for seamless integration.
|
||||
//! - **Runtime-agnostic**: Works with any async runtime (Tokio, async-std, smol, Embassy, etc.)
|
||||
//! - **Type-state pattern**: The API guides you with compile-time errors if you wire dependencies
|
||||
//! incorrectly. This is what prevents cycles at compile time.
|
||||
@@ -433,6 +436,53 @@
|
||||
//! # };
|
||||
//! ```
|
||||
//!
|
||||
//! ## Custom Types
|
||||
//!
|
||||
//! **dagx works with ANY type automatically!** As long as your type implements `Clone + Send + Sync + 'static`,
|
||||
//! the `#[task]` macro generates the necessary extraction logic:
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use dagx::{task, DagRunner, Task};
|
||||
//!
|
||||
//! // Just derive Clone - that's all you need!
|
||||
//! #[derive(Clone)]
|
||||
//! struct User {
|
||||
//! name: String,
|
||||
//! age: u32,
|
||||
//! }
|
||||
//!
|
||||
//! struct CreateUser;
|
||||
//! #[task]
|
||||
//! impl CreateUser {
|
||||
//! async fn run() -> User {
|
||||
//! User { name: "Alice".to_string(), age: 30 }
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! struct FormatUser;
|
||||
//! #[task]
|
||||
//! impl FormatUser {
|
||||
//! async fn run(user: &User) -> String {
|
||||
//! format!("{} is {} years old", user.name, user.age)
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! # async {
|
||||
//! let dag = DagRunner::new();
|
||||
//!
|
||||
//! let user = dag.add_task(CreateUser);
|
||||
//! let formatted = dag.add_task(FormatUser).depends_on(&user);
|
||||
//!
|
||||
//! dag.run(|fut| { tokio::spawn(fut); }).await.unwrap();
|
||||
//!
|
||||
//! assert_eq!(dag.get(formatted).unwrap(), "Alice is 30 years old");
|
||||
//! # };
|
||||
//! ```
|
||||
//!
|
||||
//! **No trait implementations needed!** Works with nested structs, collections, enums, and any
|
||||
//! other custom type. See [`examples/custom_types.rs`](https://github.com/swaits/dagx/blob/main/examples/custom_types.rs)
|
||||
//! for a complete example with complex nested types.
|
||||
//!
|
||||
//! # Runtime Agnostic
|
||||
//!
|
||||
//! dagx works with any async runtime. The library has been tested with:
|
||||
|
||||
+5
-1
@@ -8,7 +8,11 @@ use std::future::Future;
|
||||
/// A unit of async work with typed inputs and outputs.
|
||||
///
|
||||
/// Use the [`task`](crate::task) macro to implement this trait. The macro automatically
|
||||
/// derives `Input` and `Output` types from your `run()` method signature.
|
||||
/// derives `Input` and `Output` types from your `run()` method signature and generates
|
||||
/// type-specific extraction logic in `extract_and_run()`.
|
||||
///
|
||||
/// **Custom types work automatically!** As long as your output type implements
|
||||
/// `Clone + Send + Sync + 'static`, the macro handles everything. No trait implementations needed!
|
||||
///
|
||||
/// # Task Patterns
|
||||
///
|
||||
|
||||
Reference in new issue
Block a user