camel-component-cron 0.24.0

Cron component for rust-camel — triggers Routes on Unix cron schedules
Documentation
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
# rust-camel

A Rust-native, Tower-native integration framework inspired by [Apache Camel](https://camel.apache.org/), built for async pipelines, EIP patterns, and production observability.

> **Status:** Pre-release (`0.24.0`). APIs will change.

## Overview

rust-camel lets you define message routes between components using a fluent builder API. The data plane (exchange processing, EIP patterns, middleware) is Tower-native — every processor and producer is a `Service<Exchange>`. The control plane (components, endpoints, consumers, lifecycle) uses its own trait hierarchy.

Current components: `timer`, `cron`, `log`, `direct`, `exec`, `mock`, `file`, `http`, `ws`/`wss`, `kafka`, `mqtt`, `redis`, `sql`, `jms`, `cxf`, `container`, `controlbus`, `validator`, `xslt`, `xj`, `master`, `opensearch`, `llm`, `surrealdb`, `grpc`, `seda`, `keycloak`, `wasm`.

## Architecture

rust-camel separates two planes:

- **Data plane** — Tower-native. Every processor and producer is a `Service<Exchange>`. EIP patterns compose as Tower middleware.
- **Control plane** — its own trait hierarchy: `Component`, `Endpoint`, `Consumer`, route lifecycle, supervision, hot-reload.

```
┌──────────────────────────────────────────────────────┐
│                    Your Application                  │
│         RouteBuilder / YAML DSL / camel-config       │
└──────────────────────┬───────────────────────────────┘
                       │
┌──────────────────────▼───────────────────────────────┐
│                    camel-core                        │
│  CamelContext — composition root                     │
│                                                      │
│  ┌──────────────────────────────────────────────┐    │
│  │  Data plane (Tower)                          │    │
│  │  Exchange → Service<Exchange> pipeline       │    │
│  │  EIP processors as Tower middleware          │    │
│  └──────────────────────────────────────────────┘    │
│                                                      │
│  ┌──────────────────────────────────────────────┐    │
│  │  Control plane                               │    │
│  │  Route lifecycle, supervision, hot-reload    │    │
│  │  RuntimeBus (CQRS), event journal (redb)     │    │
│  └──────────────────────────────────────────────┘    │
└──────────────────────────────────────────────────────┘
          │                          │
┌─────────▼──────────┐   ┌───────────▼────────────────┐
│   camel-processor  │   │   Components               │
│   EIP patterns     │   │   timer, log, http, file,  │
│   (Tower layers)   │   │   kafka, redis, sql, opensearch, ...,  │
└────────────────────┘   └────────────────────────────┘
```

> The internal DDD/CQRS/hexagonal structure of `camel-core` is an implementation detail — see [`crates/camel-core/README.md`](crates/camel-core/README.md) for those internals.

### Runtime Bus

```rust
// Commands modify state
ctx.runtime().execute(RuntimeCommand::StartRoute {
    route_id: "my-route".into(),
    command_id: "cmd-1".into(),
    causation_id: None,
}).await?;

// Queries read from projections (not controller)
let status = ctx.runtime_route_status("my-route").await?;
```

### Optional Durability

```rust
// Enable redb-backed event journal for runtime state recovery
let ctx = CamelContext::builder()
    .runtime_store(camel_core::InMemoryRuntimeStore::default().with_journal(std::sync::Arc::new(
        camel_core::RedbRuntimeEventJournal::new(
            ".camel/runtime.redb",
            RedbJournalOptions::default(),
        )
        .await?,
    )))
    .build()
    .await?;
```

## Quick Start with the CLI

```bash
cargo install camel-cli
camel new my-integration
cd my-integration
camel run
```

This scaffolds a project with a `Camel.toml`, `routes/hello.yaml`, and runs it.
See [`crates/camel-cli/README.md`](crates/camel-cli/README.md) for all CLI commands.

```bash
# Generate OpenAPI document from REST route files
camel openapi generate routes.yaml --title "My API"
```

## Docker

Pre-built images are available on [GHCR](https://github.com/kennycallado/rust-camel/pkgs/container/rust-camel) and [Docker Hub](https://hub.docker.com/r/kennycallado/rust-camel).

```bash
# Pull the scratch image (production)
docker pull ghcr.io/kennycallado/rust-camel:latest

# Pull the alpine image (debugging)
docker pull ghcr.io/kennycallado/rust-camel:latest-alpine

# Run with routes mounted
docker run -v $(pwd)/routes:/app/routes ghcr.io/kennycallado/rust-camel:latest camel run

# Interactive shell (alpine)
docker run -it -v $(pwd):/app ghcr.io/kennycallado/rust-camel:latest-alpine sh

# Docker Hub equivalent
docker pull kennycallado/rust-camel:latest
```

Two image variants are published per release:

| Tag suffix | Base        | Use case                            |
| ---------- | ----------- | ----------------------------------- |
| _(none)_   | scratch     | Production. Minimal attack surface. |
| `-alpine`  | alpine:3.21 | Debugging. Includes busybox shell.  |

Both variants support `linux/amd64` and `linux/arm64`.

## Quick Rust Example

```rust
use camel_api::{CamelError, Value};
use camel_builder::RouteBuilder;
use camel_component_log::LogComponent;
use camel_component_timer::TimerComponent;
use camel_core::context::CamelContext;

#[tokio::main]
async fn main() -> Result<(), CamelError> {
    tracing_subscriber::fmt::init();

    let mut ctx = CamelContext::builder().build().await?;
    ctx.register_component(TimerComponent::new());
    ctx.register_component(LogComponent::new());

    let route = RouteBuilder::from("timer:tick?period=1000&repeatCount=5")
        .set_header("source", Value::String("timer".into()))
        .to("log:info?showHeaders=true")
        .build()?;

    ctx.add_route_definition(route).await?;
    ctx.start().await?;

    println!("Press Ctrl+C to stop.");
    tokio::signal::ctrl_c().await.ok();

    ctx.stop().await?;
    Ok(())
}
```

```sh
cargo run
```

## REST DSL & OpenAPI

Define REST APIs declaratively in YAML with automatic JSON binding, path
templates, schema validation, and OpenAPI document generation.

```yaml
rest:
  - host: 0.0.0.0
    port: 8080
    path: /api/users
    operations:
      - method: GET
        operation_id: listUsers
        to: direct:listUsers
        produces: application/json
      - method: POST
        operation_id: createUser
        consumes: application/json
        produces: application/json
        success_status: 201
        to: direct:createUser
        request_schema:
          type: object
          properties:
            name:
              type: string
            email:
              type: string
          required: [name, email]
      - method: GET
        path: /{id}
        operation_id: getUser
        to: direct:getUser
      - method: DELETE
        path: /{id}
        operation_id: deleteUser
        to: direct:deleteUser
        success_status: 204
```

The `rest:` block lowers to `http:` consumer routes with:
- `unmarshal(json)` for body verbs (POST/PUT/PATCH)
- JSON schema validation when `request_schema` is present (→ 400 on failure)
- `marshal(json)` + `Content-Type: application/json` on the response path
- Default status codes (200/201/204) via `CamelHttpResponseCode` header

Generate an OpenAPI 3.0.3 document from REST routes:

```bash
camel openapi generate routes.yaml --title "Users API" --version "1.0.0"
```

See [`examples/rest-crud/`](examples/rest-crud/README.md) for a complete
runnable example with in-memory CRUD storage and static file co-hosting.

## Crate Map

| Crate                       | Description                                                                                                                                                                                                                                                  |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --- | ------------------------------------ |
| `camel-api`                 | Core types: `Exchange`, `Message`, `Body`, `CamelError`, `BoxProcessor`, `ProcessorFn`, `RuntimeCommand`, `RuntimeQuery`, `RuntimeEvent`, `FromBody`, `impl_from_body_via_serde!`                                                                            |
| `camel-core`                | Runtime engine with DDD/CQRS: `CamelContext`, domain aggregates, ports, adapters, event journal                                                                                                                                                              |
| `camel-config`              | Configuration: `CamelConfig`, route discovery from YAML files with glob patterns                                                                                                                                                                             |
| `camel-builder`             | Fluent `RouteBuilder` API                                                                                                                                                                                                                                    |
| `camel-component`           | `Component`, `Endpoint`, `Consumer` traits                                                                                                                                                                                                                   |
| `camel-processor`           | EIP processors: `Filter`, `Choice`, `Splitter`, `StreamingSplitter`, `Aggregator`, `WireTap`, `Multicast`, `SetHeader`, `MapBody`, `Marshal`/`Unmarshal` + Tower `Layer` types                                                                               |
| `camel-endpoint`            | Endpoint URI parsing utilities; `UriConfig` derive macro for typed component config                                                                                                                                                                          |
| `camel-endpoint-macros`     | Proc-macro crate backing `#[derive(UriConfig)]`                                                                                                                                                                                                              |
| `camel-wit`                 | WIT interface definitions crate for camel components                                                                                                                                                                                                            |
| `camel-bean`                | Bean/Registry system for dependency injection and business logic integration                                                                                                                                                                                 |
| `camel-bean-macros`         | Proc-macro crate for `#[bean]` attribute                                                                                                                                                                                                                     |
| `camel-dsl`                 | YAML DSL: load and run routes from `.yaml` files                                                                                                                                                                                                             |
| `camel-health`              | Health check types and endpoint support                                                                                                                                                                                                                      |
| `camel-platform-kubernetes` | Kubernetes-native platform SPI: leader election, readiness gates, pod identity                                                                                                                                                                               |
| `camel-timer`               | Timer source component                                                                                                                                                                                                                                       |
| `camel-cron`                | Cron source component — calendar-triggered scheduling via Unix 5-field cron expressions, backed by `CronService` SPI                                                                                                                                        |
| `camel-log`                 | Log sink component                                                                                                                                                                                                                                           |
| `camel-direct`              | In-memory synchronous component                                                                                                                                                                                                                              |
| `camel-mock`                | Test component with assertions on received exchanges (`await_exchanges`, `ExchangeAssert`)                                                                                                                                                                   |
| `camel-test`                | Integration test harness                                                                                                                                                                                                                                     |
| `camel-controlbus`          | Control routes dynamically from within routes                                                                                                                                                                                                                |
| `camel-validator`           | Validate body against JSON/YAML schemas, plus XSD via xml-bridge                                                                                                                                                                                             |
| `camel-http`                | HTTP producer (client) and HTTP consumer (server, native streaming)                                                                                                                                                                                          |
| `camel-file`                | File producer and consumer                                                                                                                                                                                                                                   |
| `camel-kafka`               | Kafka producer and consumer with SSL/SASL and manual commit                                                                                                                                                                                                  |
| `camel-mqtt`                | MQTT 3.1.1 producer and consumer (rumqttc-v4-next) with QoS 0/1/2, manual/auto ack, TLS via mqtts://                                                                                                                                                         |
| `camel-redis`               | Redis producer and consumer                                                                                                                                                                                                                                  |
| `camel-opensearch`          | OpenSearch producer with 7 operations (INDEX, SEARCH, GET, DELETE, UPDATE, BULK, MULTIGET)                                                                                                                                                                   |
| `camel-sql`                 | SQL producer/consumer with IN clause separator, SSL/TLS, streaming result support                                                                                                                                                                            |
| `camel-surrealdb`           | SurrealDB multi-model (document, graph, vector, live) with 9 operations                                                                                                                                                                                      |
| `camel-jms`                 | JMS producer and consumer via native-image bridge (ActiveMQ Classic, Artemis)                                                                                                                                                                                |
| `camel-component-cxf`       | SOAP/Web Services via Apache CXF native-image bridge: SOAP 1.1/1.2, WSDL, WS-Security, multi-tenant profiles, PAYLOAD mode                                                                                                                                   |
| `camel-component-exec`      | Fail-closed system command execution with profile-pinned binaries, per-element arg-policy, env sanitization, cwd confinement, timeout with process-group kill (`exec:{profile}`)                                                                             |
| `camel-grpc`                | gRPC producer and consumer with dynamic proto resolution, unary + server/client/bidi streaming                                                                                                                                                               |
| `camel-xslt`                | XSLT 3.0 transformation via xml-bridge (`xslt:<stylesheet>`) — [example](examples/xslt-example/README.md)                                                                                                                                                    |
| `camel-xj`                  | XML↔JSON conversion via xml-bridge (`xj:<stylesheet>?direction=xml2json\|json2xml`) — [example](examples/xj-example/README.md)                                                                                                                              |
| `camel-container`           | Docker container producer/consumer via `bollard`. Container lifecycle, volume mounts, exec, network operations                                                                                                                                               |
| `camel-component-llm`       | LLM chat (streaming + materialized), embeddings, tool calling, multi-turn conversations, response cache, cost observability, retry, and concurrency control via OpenAI, Ollama, or Mock. Strict siumai adapter boundary (ADR-0020) (`llm:chat`, `llm:embed`) |
| `camel-language-api`        | Language trait API: `Language`, `Expression`, `Predicate`                                                                                                                                                                                                    |
| `camel-language-simple`     | Simple Language: `${header.x}`, `${body}`, operators, `&&`/\`                                                                                                                                                                                                |     | \`, boolean literals, null semantics |
| `camel-language-js`         | JavaScript scripting language for expressions and side effects                                                                                                                                                                                               |
| `camel-language-rhai`       | Rhai scripting language for full expression power                                                                                                                                                                                                            |
| `camel-language-jsonpath`   | RFC 9535 JSONPath expressions: `$.items[*].price`. Requires `lang-jsonpath` feature.                                                                                                                                                                         |
| `camel-language-xpath`      | XPath 1.0 language for XML body queries: `/books/book[1]/title`. Requires `lang-xpath` feature.                                                                                                                                                              |
| `camel-prometheus`          | Prometheus metrics exporter with /metrics endpoint                                                                                                                                                                                                           |
| `camel-otel`                | OpenTelemetry tracing and metrics exporter                                                                                                                                                                                                                   |
| [`examples/rest-crud`]       | REST DSL + OpenAPI example — CRUD API with schema validation, static co-hosting                                                                                                                                                                               |

## Building & Testing

```sh
cargo build --workspace
cargo test --workspace
cargo bench --workspace
```

The benchmark suite uses [Criterion](https://bheisler.github.io/criterion.rs/book/) with HTML reports. Per-crate inline benchmarks cover core types, processors, and the DSL. The `camel-bench` crate provides integration pipeline benchmarks.

### Test Coverage

```sh
scripts/coverage.sh
```

Requires `cargo-llvm-cov`. Coverage baseline is enforced via `coverage.toml` (currently 75% minimum). Adjust the baseline there if coverage changes intentionally.

## Implemented EIP Patterns

| Pattern                     | Builder Method                                | Description                                                                                                                                               |
| --------------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Aggregator                  | `.aggregate(config)`                          | Correlate and aggregate exchanges with size/timeout completion, expression correlation, force-complete-on-stop                                            |
| Content-Based Router        | `.choice()` / `.when()`                       | Route based on exchange content                                                                                                                           |
| Content Enricher            | `.enrich(uri)` / `.poll_enrich(uri, timeout)` | Merge additional content mid-route via producer (`enrich`) or polling consumer (`pollEnrich`); pluggable `EnrichmentStrategy` (default `UseEnrichedBody`) |
| Delayer                     | `.delay()` / `delay:`                         | Fixed or dynamic delay (header-based)                                                                                                                     |
| doTry / doCatch / doFinally | `.do_try()` / `do_try:`                       | Lexical-scope try/catch/finally with ADR-0019 dispositions                                                                                                |
| Dynamic Router              | `.dynamic_router(expr)`                       | Expression-based routing with slip pattern                                                                                                                |
| Routing Slip                | `.routing_slip(expr)`                         | Route through a sequence of endpoints determined at runtime                                                                                               |
| Filter                      | `.filter(predicate)`                          | Forward exchange only when predicate is true                                                                                                              |
| Load Balancer               | `.load_balance()`                             | Distribute across endpoints with RoundRobin/Random/Weighted/Failover                                                                                      |
| Loop                        | `.loop_count(n)` / `loop:`                    | Iterate a sub-pipeline N times or while a predicate holds true                                                                                            |
| Marshal / Unmarshal         | `.marshal(fmt)` / `.unmarshal(fmt)`           | Serialize/deserialize bodies using pluggable data formats (JSON, XML, ZIP, CSV)                                                                           |
| Multicast                   | `.multicast()`                                | Send the same exchange to multiple endpoints                                                                                                              |
| RecipientList               | `.recipient_list(config)`                     | Dynamically resolve endpoint URIs from an expression at runtime                                                                                           |
| Splitter                    | `.split(config)`                              | Split one exchange into multiple fragments (body lines, ZIP entries, streaming)                                                                           |
| Stream Cache                | `.stream_cache(n)` / `stream_cache:`          | Materialize `Body::Stream` into `Body::Bytes` with configurable threshold (128 KB default)                                                                |
| Throttler                   | `.throttle(n, duration)`                      | Rate limiting with Delay/Reject/Drop strategies                                                                                                           |
| WireTap                     | `.wire_tap(uri)`                              | Fire-and-forget copy to a tap endpoint                                                                                                                    |

Run an example:

```sh
 cargo run -p aggregator
 cargo run -p bean-demo
 cargo run -p circuit-breaker
 cargo run -p config-basic
 cargo run -p config-profiles
 cargo run -p container-example
 cargo run -p content-based-routing
 cargo run -p controlbus
 cargo run -p do-try
 cargo run -p dynamic-router
 cargo run -p recipientlist
 cargo run -p routing-slip
 cargo run -p error-handling
 cargo run -p file-pipeline
 cargo run -p file-polling
 cargo run -p hello-world
 cargo run -p http-client
 cargo run -p http-server
 cargo run -p http-streaming
 cargo run -p kafka-example
 cargo run -p jms-example
 cargo run -p opensearch-example
 cargo run -p language-rhai
 cargo run -p language-simple
 cargo run -p lazy-route
 cargo run -p load-balancer
 cargo run -p loop-example
 cargo run -p log-eip
 cargo run -p marshal-unmarshal
 cargo run -p metrics-demo
 cargo run -p multicast
 cargo run -p multi-route-direct
 cargo run -p otel-demo
 cargo run -p pipeline-concurrency
 cargo run -p prometheus-demo
 cargo run -p showcase
 cargo run -p splitter
 cargo run -p sql-example
 cargo run -p sql-streaming
 cargo run -p throttler
 cargo run -p transform-pipeline
 cargo run -p wiretap
 cargo run -p xml-body
 cargo run -p yaml-dsl
```

## Security Features

rust-camel includes production-ready security features:

### SSRF Protection (HTTP Component)

```rust
// Block private IPs by default
RouteBuilder::from("direct:start")
    .to("http://api.example.com?allowInternal=false")
    .build()?

// Custom blocked hosts
RouteBuilder::from("direct:start")
    .to("http://api.example.com?blockedHosts=localhost,internal.company.com")
    .build()?
```

### Path Traversal Protection (File Component)

All file operations validate that resolved paths remain within the configured base directory. Attempts to use `../` or absolute paths outside base are rejected.

### Timeouts

All I/O operations have configurable timeouts:

- File: `readTimeout`, `writeTimeout` (default: 30s)
- HTTP: `connectTimeout`, `responseTimeout`

### Memory Limits

Aggregator supports `max_buckets` and `bucket_ttl` to prevent memory leaks.

## Observability

### Correlation IDs

Every exchange has a unique `correlation_id` for distributed tracing.

### Metrics

Implement `MetricsCollector` trait to integrate with Prometheus, OpenTelemetry, etc.

### Prometheus Metrics

Export metrics to Prometheus with automatic lifecycle management:

```rust
use camel_prometheus::PrometheusService;

let ctx = CamelContext::builder().build().await?
    .with_lifecycle(PrometheusService::new(9090))
    .with_tracing();

ctx.start().await?;
// Prometheus server starts automatically
```

Available metrics:

- `camel_exchanges_total{route}` - Total exchanges processed
- `camel_errors_total{route, error_type}` - Total errors
- `camel_exchange_duration_seconds{route}` - Exchange processing duration (histogram)
- `camel_queue_depth{route}` - Current queue depth
- `camel_circuit_breaker_state{route}` - Circuit breaker state

**Architecture:** `PrometheusService` implements `Lifecycle` trait (following Apache Camel's Service pattern, adapted to avoid tower::Service confusion).

### Health Monitoring

Built-in health endpoints for Kubernetes:

- `/healthz` - Liveness probe
- `/readyz` - Readiness probe
- `/health` - Detailed health report

Platform SPI support for Kubernetes:

- Leader election via Kubernetes Leases
- Readiness gate via pod status conditions
- Pod identity auto-detection from Downward API

```yaml
livenessProbe:
  httpGet:
    path: /healthz
    port: 9090
```

## Route Lifecycle Management

rust-camel supports controlling when and how routes start:

### Auto Startup

By default, all routes start automatically when `ctx.start()` is called. You can disable this:

```rust
let route = RouteBuilder::from("timer:tick")
    .route_id("lazy-route")
    .auto_startup(false)  // Won't start automatically
    .to("log:info")
    .build()?;
```

### Startup Order

Control the order in which routes start (useful for dependencies):

```rust
let route_a = RouteBuilder::from("direct:a")
    .route_id("route-a")
    .startup_order(10)  // Starts first
    .to("log:info")
    .build()?;

let route_b = RouteBuilder::from("direct:b")
    .route_id("route-b")
    .startup_order(20)  // Starts after route-a
    .to("direct:a")
    .build()?;
```

### Runtime Control

Control routes dynamically from code or from other routes:

```rust
// From code:
let runtime = ctx.runtime();
runtime.execute(RuntimeCommand::StartRoute {
    route_id: "lazy-route".into(),
    command_id: "cmd-start-lazy-route".into(),
    causation_id: None,
}).await?;
runtime.execute(RuntimeCommand::StopRoute {
    route_id: "route-a".into(),
    command_id: "cmd-stop-route-a".into(),
    causation_id: None,
}).await?;

// From another route (using controlbus):
RouteBuilder::from("timer:monitor")
    .set_header("CamelRouteId", Value::String("backup-route".into()))
    .to("controlbus:route?action=start")
    .build()?
```

See `examples/lazy-route` for a complete example.

## Type Converters

The pipeline automatically coerces the exchange body to the type a component endpoint declares via `body_contract()`. No manual casting needed in `.process()` closures.

```rust
// Declare what your endpoint expects (component author):
fn body_contract(&self) -> Option<BodyType> {
    Some(BodyType::Text)  // pipeline coerces to Text before calling producer
}

// Deserialize body into any type (route author):
use camel_api::impl_from_body_via_serde;
use serde::Deserialize;

#[derive(Deserialize)]
struct Order { id: u64, amount: f64 }
impl_from_body_via_serde!(Order);

RouteBuilder::from("direct:orders")
    .process(|ex| async move {
        let order: Order = ex.body_as::<Order>()?;
        // ...
        Ok(ex)
    })
    .to("sql:insert into orders ...")
    .build()?;
```

Built-in `FromBody` impls: `String`, `Vec<u8>`, `Bytes`, `serde_json::Value`.

## Error Handling

rust-camel provides sophisticated error handling with retry policies and dead letter channels.

### RedeliveryPolicy with Jitter

Configure retry behavior with exponential backoff and jitter:

```rust
use camel_api::error_handler::{ErrorHandlerConfig, RedeliveryPolicy};
use std::time::Duration;

let error_handler = ErrorHandlerConfig::dead_letter_channel("log:errors")
    .on_exception(|e| matches!(e, CamelError::Io(_)))
    .retry(3)  // Max 3 retry attempts
    .with_backoff(
        Duration::from_millis(100),  // Initial delay: 100ms
        2.0,                          // Multiplier: 2x
        Duration::from_secs(10)      // Max delay: 10s
    )
    .with_jitter(0.2)  // ±20% randomization (recommended: 0.1-0.3)
    .build();
```

**Jitter Benefits:**

- Prevents thundering herd in distributed systems
- Recommended values: 0.1-0.3 (10-30%)
- Adds randomization: `delay ± (delay * jitter_factor)`

### Camel-Compatible Headers

During retries, these headers are automatically set:

- `CamelRedelivered` - `true` when exchange is being retried
- `CamelRedeliveryCounter` - Current retry attempt (1-indexed)
- `CamelRedeliveryMaxCounter` - Maximum retry attempts

### RouteBuilder shorthand

```rust
RouteBuilder::from("direct:input")
    .route_id("shorthand")
    .dead_letter_channel("log:dlc")
    .on_exception(|e| matches!(e, CamelError::Io(_)))
        .retry(3)
        .handled_by("log:io-errors")
    .end_on_exception()
    .to("mock:result")
    .build()?;
```

### YAML Configuration

```yaml
routes:
  - id: "retry-example"
    from: "timer:tick"
    error_handler:
      dead_letter_channel: "log:dlc"
      retry:
        max_attempts: 3
        initial_delay_ms: 100
        multiplier: 2.0
        max_delay_ms: 10000
        jitter_factor: 0.2
      on_exceptions:
        - kind: "ProcessorError"
          message_contains: "validation"
          retry:
            max_attempts: 1
    steps:
      - to: "direct:processor"
```

### Exception Disposition — Propagate, Handled, Continued

Every `on_exception` clause has a **disposition** that controls what happens after the error handler runs:

| Disposition | Behavior                                                                                                    |
| ----------- | ----------------------------------------------------------------------------------------------------------- |
| `Propagate` | Error is re-thrown to upstream after DLC/handler runs (default)                                             |
| `Handled`   | Error is absorbed as `Ok(Exchange)`. Pipeline stops — subsequent steps do NOT run                           |
| `Continued` | Error is cleared from the Exchange. Pipeline **continues** to the next step — subsequent steps run normally |

In the builder API, use `ErrorHandlerConfig` with `.continued(true)` or `.handled(true)`:

```rust
use camel_api::error_handler::ErrorHandlerConfig;

let eh = ErrorHandlerConfig::dead_letter_channel("log:dlc")
    .on_exception(|e| matches!(e, CamelError::ProcessorError(_)))
    .continued(true)    // ← clear error, pipeline continues
    .retry(1)
    .build();

let route = RouteBuilder::from("direct:input")
    .route_id("continued-example")
    .error_handler(eh)
    .to("log:result")       // ← runs even after the error
    .build()?;
```

In YAML, use the `continued: true` field:

```yaml
error_handler:
  dead_letter_channel: "log:errors"
  on_exceptions:
    - kind: ProcessorError
      continued: true
```

The `continued` and `handled` fields are mutually exclusive — setting both to `true` is a compile error.

See `examples/error-handling` for complete examples, including Route 10 which demonstrates `continued=true`.

## Configuration

rust-camel supports external configuration via `Camel.toml` files using the `camel-config` crate:

### Configuration File

Create a `Camel.toml` file:

```toml
[default]
routes = ["routes/**/*.yaml"]
log_level = "INFO"

# Component defaults - apply to all endpoints
[default.components.http]
connect_timeout_ms = 5000
allow_internal = false

[default.components.kafka]
brokers = "localhost:9092"
group_id = "camel"

[default.components.redis]
host = "localhost"
port = 6379

[default.components.opensearch]
host = "localhost"
port = 9200

[default.components.sql]
max_connections = 5

[default.components.file]
delay_ms = 500

[default.components.container]
docker_host = "unix:///var/run/docker.sock"

# Observability
[default.observability.prometheus]
enabled = true
port = 9090

[production]
log_level = "ERROR"

[production.components.kafka]
brokers = "prod-kafka:9092"

[production.components.redis]
host = "prod-redis"
```

### Component Defaults

Each component supports global defaults that apply to all endpoints. URI parameters always take precedence:

```rust
// Uses global connect_timeout_ms (5000) from Camel.toml
.to("http://api.example.com/data")

// Overrides global setting with URI parameter
.to("http://api.example.com/data?connectTimeout=10000")
```

Supported component configurations:

- **`[components.http]`**: `connect_timeout_ms`, `response_timeout_ms`, `max_connections`, `max_body_size`, `max_request_body`, `allow_internal`
- **`[components.kafka]`**: `brokers`, `group_id`, `session_timeout_ms`, `request_timeout_ms`, `auto_offset_reset`, `security_protocol`, `partition_assignment_strategy`. Named clusters under `[components.kafka.brokers_named.<name>]` each with `brokers`, optional `security_protocol`, `sasl_auth_type`, `client_id`, and `rdkafka_config` escape hatch. Reference via `?brokerName=<name>` in the endpoint URI.
- **`[components.redis]`**: `host`, `port`
- **`[components.sql]`**: `max_connections`, `min_connections`, `idle_timeout_secs`, `max_lifetime_secs`, `ssl_mode`, `ssl_root_cert`, `ssl_cert`, `ssl_key`
- **`[components.jms]`**: `default_broker`, `max_bridges`, `bridge_cache_dir`, `bridge_start_timeout_ms`, `broker_reconnect_interval_ms`. Brokers are declared as named entries under `[components.jms.brokers.<name>]`, each with `broker_url`, `broker_type` (`activemq`|`artemis`), and optional `username`/`password`. URI schemes `activemq:` and `artemis:` lock the broker type automatically and support shorthand destinations (e.g. `activemq:orders` → queue). Use the `broker=<name>` URI query param to select a specific broker from the pool.
- **`[components.file]`**: `delay_ms`, `initial_delay_ms`, `read_timeout_ms`, `write_timeout_ms`
- **`[components.container]`**: `docker_host`
- **`[components.ws]`**: `max_connections`, `max_message_size`, `heartbeat_interval_ms`, `idle_timeout_ms`

Each optional component (http, ws, kafka, redis, sql, jms, file, container) implements `ComponentBundle` — it owns its config key, deserializes its own TOML block, and registers one or more schemes. See `examples/custom-component-bundle` for a full walkthrough of implementing your own bundle.

### Loading Configuration

```rust
use camel_api::CamelError;
use camel_component_log::LogComponent;
use camel_component_timer::TimerComponent;
use camel_config::{CamelConfig, discover_routes};
use camel_core::CamelContext;

// Load configuration
let config = CamelConfig::from_file("Camel.toml")
    .map_err(|e| CamelError::Config(e.to_string()))?;

// Create context and register components
let mut ctx = CamelContext::builder().build().await?;
ctx.register_component(TimerComponent::new());
ctx.register_component(LogComponent::new());

// Discover and load routes from config patterns
let routes = discover_routes(&config.routes)
    .map_err(|e| CamelError::Config(e.to_string()))?;
for route in routes {
    ctx.add_route_definition(route).await?;
}

ctx.start().await?;
```

### Route Files

Create YAML route files:

```yaml
# routes/hello.yaml
routes:
  - id: "hello-timer"
    from: "timer:tick?period=1000"
    steps:
      - to: "log:info"
```

### Environment Variables

Override configuration with environment variables:

```bash
# Select profile
export CAMEL_PROFILE=production

# Override specific values
export CAMEL_LOG_LEVEL=DEBUG
export CAMEL_ROUTES_0="custom/*.yaml"
```

### Features

- **Profile support**: Multiple environments in one file
- **Route discovery**: Auto-load routes from glob patterns
- **Component defaults**: Set global defaults for HTTP, Kafka, Redis, SQL, File, Container
- **Environment overrides**: Override any value with `CAMEL_*` prefix
- **Deep merging**: Nested configs merge properly
- **URI precedence**: URI parameters always override global defaults

### Component Defaults

Configure global defaults for all component endpoints in `Camel.toml`:

```toml
[default.components.http]
connect_timeout_ms = 5000
allow_internal = false

[default.components.kafka]
brokers = "localhost:9092"
group_id = "my-app"

[default.components.redis]
host = "localhost"
port = 6379

[default.components.sql]
max_connections = 10

[default.components.file]
delay_ms = 1000

[default.components.container]
docker_host = "unix:///var/run/docker.sock"
```

URI parameters always take precedence over global defaults:

```rust
// Uses global connect_timeout_ms (5000) from Camel.toml
.to("http://api.example.com/data")

// Overrides global setting with URI parameter
.to("http://api.example.com/data?connectTimeout=10000")
```

See `docs/configuration.md` for full details.

## JSON Schema

The full DSL AST has a published JSON Schema:

- **URL:** `https://raw.githubusercontent.com/kennycallado/rust-camel/main/schemas/dsl/route-schema.json`
- **Local:** `schemas/dsl/route-schema.json` (regenerate with `cargo xtask schema`).

### Using `$schema`

Add the `$schema` key to your JSON route files for editor autocomplete and SDK validation:

```json
{
  "$schema": "https://raw.githubusercontent.com/kennycallado/rust-camel/main/schemas/dsl/route-schema.json",
  "routes": [...]
}
```

The parser silently ignores the key. See [`schemas/dsl/README.md`](./schemas/dsl/README.md) for scope and versioning.

## License

Apache-2.0