Skip to main content

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}