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
//! Core durable-execution contracts shared by Runledger storage, runtime, and
//! application crates.
//!
//! Use this crate for the storage-agnostic pieces of the job system:
//! - [`jobs::JobHandler`] and [`jobs::JobHandlerRegistry`] for handler contracts
//! - [`jobs::JobContext`], [`jobs::JobProgress`], and [`jobs::JobFailure`] for
//! execution-time state
//! - workflow enqueue builders and validation helpers such as
//! [`jobs::WorkflowDagBuilder`], [`jobs::WorkflowRunEnqueueBuilder`], and
//! [`jobs::validate_workflow_run_enqueue`]
//!
//! Use workflow builders when work has dependencies, fan-out/fan-in, external
//! gates, or workflow-level idempotency. A single direct job is appropriate only
//! for one independent unit of retried work.
//!
//! This crate does not provide persistence or worker loops. Pair it with
//! `runledger-postgres` for PostgreSQL-backed storage and `runledger-runtime`
//! for worker, scheduler, and reaper execution.
//!
//! # Copy-Paste Examples
//!
//! - [Enqueue one job](https://github.com/featherenvy/runledger/blob/master/runledger-postgres/examples/enqueue_job.rs)
//! - [Enqueue a workflow DAG](https://github.com/featherenvy/runledger/blob/master/runledger-postgres/examples/workflow_dag.rs)
//! - [Use an external workflow gate](https://github.com/featherenvy/runledger/blob/master/runledger-postgres/examples/external_gate.rs)
//! - [Run a worker binary](https://github.com/featherenvy/runledger/blob/master/runledger-runtime/examples/worker_binary.rs)
//! - [Create a scheduled job entrypoint](https://github.com/featherenvy/runledger/blob/master/runledger-postgres/examples/schedule_job.rs)
//!
//! # Prelude
//!
//! Import the common contracts with:
//!
//! ```rust
//! use runledger_core::prelude::*;
//! ```
//!
//! The prelude intentionally exports contract types and builders, not storage or
//! runtime APIs. Pair it with `runledger_postgres::prelude::*` and
//! `runledger_runtime::prelude::*` in integration crates.
//!
//! # Build A Job Handler
//!
//! ```rust
//! use runledger_core::prelude::*;
//! use serde_json::Value;
//!
//! struct SendEmail;
//!
//! #[async_trait]
//! impl JobHandler for SendEmail {
//! fn job_type(&self) -> JobType<'static> {
//! JobType::new("jobs.email.send")
//! }
//!
//! async fn execute(&self, _context: JobContext, _payload: Value) -> Result<(), JobFailure> {
//! Ok(())
//! }
//! }
//! ```
//!
//! # Build A Workflow DAG
//!
//! ```rust
//! use runledger_core::prelude::*;
//!
//! let crawl_payload = serde_json::json!({"profile_id": "p_123"});
//! let classify_payload = serde_json::json!({"profile_id": "p_123"});
//! let metadata = serde_json::json!({"source": "api"});
//!
//! let run = WorkflowDagBuilder::new("profiles.research", &metadata)
//! .job("crawl", "profiles.crawl", &crawl_payload)?
//! .job("classify", "profiles.classify", &classify_payload)?
//! .after_success("classify", ["crawl"])?
//! .build()?;
//! # Ok::<_, WorkflowBuildError>(())
//! ```
/// Common `runledger-core` imports for consumers.
///
/// This prelude contains storage-agnostic job and workflow contracts. It avoids
/// generic `Result` or `Error` aliases so it can be glob-imported alongside
/// `runledger_postgres::prelude::*` and `runledger_runtime::prelude::*`.