cloacina_macros/lib.rs
1/*
2 * Copyright 2025-2026 Colliery Software
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#![allow(unexpected_cfgs)]
18//! # Cloacina Macros
19//!
20//! Procedural macros for defining tasks and workflows in the Cloacina framework.
21//!
22//! ## Key Features
23//!
24//! - `#[task]` — define tasks with retry policies and trigger rules
25//! - `#[workflow]` — define workflows as modules containing `#[task]` functions
26//! - Compile-time validation of task dependencies and workflow structure
27//! - Automatic task and workflow registration
28//! - Code fingerprinting for task versioning
29//!
30//! ## Example
31//!
32//! ```rust,ignore
33//! use cloacina::{task, workflow, Context, TaskError};
34//!
35//! #[workflow(name = "my_pipeline", description = "Process data")]
36//! pub mod my_pipeline {
37//! use super::*;
38//!
39//! #[task(id = "fetch", dependencies = [])]
40//! pub async fn fetch(ctx: &mut Context<Value>) -> Result<(), TaskError> { Ok(()) }
41//!
42//! #[task(id = "process", dependencies = ["fetch"])]
43//! pub async fn process(ctx: &mut Context<Value>) -> Result<(), TaskError> { Ok(()) }
44//! }
45//! ```
46
47pub(crate) mod packaged_workflow;
48mod registry;
49pub(crate) mod tasks;
50mod trigger_attr;
51mod workflow_attr;
52
53use proc_macro::TokenStream;
54
55/// Define a task with retry policies and trigger rules.
56#[proc_macro_attribute]
57pub fn task(args: TokenStream, input: TokenStream) -> TokenStream {
58 tasks::task(args, input)
59}
60
61/// Define a workflow as a module containing `#[task]` functions.
62///
63/// Applied to a `pub mod` containing `#[task]` functions. Auto-discovers tasks,
64/// validates dependencies, and generates registration code based on delivery mode:
65///
66/// - **Embedded** (default): `#[ctor]` auto-registration
67/// - **Packaged** (`features = ["packaged"]`): FFI exports for `.cloacina` packages
68///
69/// # Example
70///
71/// ```rust,ignore
72/// #[workflow(name = "my_pipeline", description = "Process data")]
73/// pub mod my_pipeline {
74/// use super::*;
75///
76/// #[task(id = "fetch", dependencies = [])]
77/// pub async fn fetch(ctx: &mut Context<Value>) -> Result<(), TaskError> { Ok(()) }
78///
79/// #[task(id = "process", dependencies = ["fetch"])]
80/// pub async fn process(ctx: &mut Context<Value>) -> Result<(), TaskError> { Ok(()) }
81/// }
82/// ```
83#[proc_macro_attribute]
84pub fn workflow(args: TokenStream, input: TokenStream) -> TokenStream {
85 workflow_attr::workflow_attr(args, input)
86}
87
88/// Define a trigger that fires a workflow on a schedule or condition.
89///
90/// # Custom poll trigger
91///
92/// ```rust,ignore
93/// #[trigger(on = "my_workflow", poll_interval = "5s")]
94/// pub async fn check_inbox() -> Result<TriggerResult, TriggerError> {
95/// // check condition, return Fire(ctx) or Skip
96/// }
97/// ```
98///
99/// # Cron trigger (T-0305)
100///
101/// ```rust,ignore
102/// #[trigger(on = "my_workflow", cron = "0 2 * * *", timezone = "UTC")]
103/// ```
104#[proc_macro_attribute]
105pub fn trigger(args: TokenStream, input: TokenStream) -> TokenStream {
106 trigger_attr::trigger_attr(args, input)
107}