1pub use camel_api::{LanguageExpressionDef, StreamSplitConfig, ValueSourceDef};
2
3#[derive(Default)]
4pub struct SecurityCompileContext {
5 pub authenticator: Option<std::sync::Arc<dyn camel_auth::TokenAuthenticator>>,
6 pub registry: Option<std::sync::Arc<camel_auth::SecurityPolicyRegistry>>,
7 pub evaluator_registry: Option<std::sync::Arc<camel_auth::PermissionEvaluatorRegistry>>,
8}
9
10impl Clone for SecurityCompileContext {
11 fn clone(&self) -> Self {
12 Self {
13 authenticator: self.authenticator.clone(),
14 registry: self.registry.clone(),
15 evaluator_registry: self.evaluator_registry.clone(),
16 }
17 }
18}
19
20impl SecurityCompileContext {
21 pub fn new(
22 authenticator: Option<std::sync::Arc<dyn camel_auth::TokenAuthenticator>>,
23 registry: Option<std::sync::Arc<camel_auth::SecurityPolicyRegistry>>,
24 ) -> Self {
25 Self {
26 authenticator,
27 registry,
28 evaluator_registry: None,
29 }
30 }
31
32 pub fn with_evaluator_registry(
33 mut self,
34 registry: std::sync::Arc<camel_auth::PermissionEvaluatorRegistry>,
35 ) -> Self {
36 self.evaluator_registry = Some(registry);
37 self
38 }
39
40 pub fn with_security_policy_registry(
41 mut self,
42 registry: std::sync::Arc<camel_auth::SecurityPolicyRegistry>,
43 ) -> Self {
44 self.registry = Some(registry);
45 self
46 }
47}
48
49#[derive(Debug, Clone, PartialEq, Eq)]
50pub enum DeclarativeConcurrency {
51 Sequential,
52 Concurrent { max: Option<usize> },
53}
54
55#[derive(Debug, Clone, PartialEq, Eq)]
56pub struct DeclarativeCircuitBreaker {
57 pub failure_threshold: u32,
58 pub open_duration_ms: u64,
59}
60
61#[derive(Debug, Clone, PartialEq)]
62pub enum DeclarativeSecurityPolicy {
63 Roles {
64 roles: Vec<String>,
65 all_required: bool,
66 trust_upstream_principal: bool,
67 },
68 Scopes {
69 scopes: Vec<String>,
70 all_required: bool,
71 trust_upstream_principal: bool,
72 },
73 Ref {
74 name: String,
75 },
76 Wasm {
81 path: String,
83 config: std::collections::HashMap<String, String>,
85 },
86 Permission {
87 policy: String,
88 resource: camel_auth::PermissionValueSource,
89 action: camel_auth::PermissionValueSource,
90 scopes: Vec<String>,
91 context: camel_auth::PermissionContextConfig,
92 cache_ttl_secs: Option<u64>,
93 cache_negative_ttl_secs: Option<u64>,
94 },
95}
96
97#[derive(Debug, Clone, PartialEq)]
98pub struct DeclarativeRedeliveryPolicy {
99 pub max_attempts: u32,
100 pub initial_delay_ms: u64,
101 pub multiplier: f64,
102 pub max_delay_ms: u64,
103 pub jitter_factor: f64,
104 pub handled_by: Option<String>,
105}
106
107#[derive(Debug, Clone, PartialEq)]
108pub struct DeclarativeOnException {
109 pub kind: Option<String>,
110 pub message_contains: Option<String>,
111 pub retry: Option<DeclarativeRedeliveryPolicy>,
112 pub steps: Vec<DeclarativeStep>,
113 pub handled: Option<bool>,
114 pub continued: Option<bool>,
115}
116
117#[derive(Debug, Clone, PartialEq, Default)]
118pub struct DeclarativeErrorHandler {
119 pub dead_letter_channel: Option<String>,
120 pub retry: Option<DeclarativeRedeliveryPolicy>,
121 pub on_exceptions: Option<Vec<DeclarativeOnException>>,
122 pub use_original_message: bool,
123}
124
125#[derive(Debug, Clone)]
126pub struct DeclarativeRoute {
127 pub from: String,
128 pub route_id: String,
129 pub auto_startup: bool,
130 pub startup_order: i32,
131 pub concurrency: Option<DeclarativeConcurrency>,
132 pub error_handler: Option<DeclarativeErrorHandler>,
133 pub circuit_breaker: Option<DeclarativeCircuitBreaker>,
134 pub security_policy: Option<DeclarativeSecurityPolicy>,
135 pub unit_of_work: Option<camel_api::UnitOfWorkConfig>,
136 pub steps: Vec<DeclarativeStep>,
137}
138
139#[derive(Debug, Clone, PartialEq, Eq)]
140pub struct ToStepDef {
141 pub uri: String,
142}
143
144impl ToStepDef {
145 pub fn new(uri: impl Into<String>) -> Self {
146 Self { uri: uri.into() }
147 }
148}
149
150#[derive(Debug, Clone, PartialEq, Eq)]
151pub enum LogLevelDef {
152 Trace,
153 Debug,
154 Info,
155 Warn,
156 Error,
157}
158
159#[derive(Debug, Clone, PartialEq)]
162pub struct LogStepDef {
163 pub message: ValueSourceDef,
164 pub level: LogLevelDef,
165}
166
167impl LogStepDef {
168 pub fn info(message: impl Into<String>) -> Self {
169 Self {
170 message: ValueSourceDef::Literal(serde_json::Value::String(message.into())),
171 level: LogLevelDef::Info,
172 }
173 }
174}
175
176#[derive(Debug, Clone, PartialEq)]
177pub struct SetHeaderStepDef {
178 pub key: String,
179 pub value: ValueSourceDef,
180}
181
182impl SetHeaderStepDef {
183 pub fn literal(key: impl Into<String>, value: impl Into<String>) -> Self {
184 Self {
185 key: key.into(),
186 value: ValueSourceDef::Literal(serde_json::Value::String(value.into())),
187 }
188 }
189}
190
191#[derive(Debug, Clone, PartialEq)]
192pub struct SetPropertyStepDef {
193 pub key: String,
194 pub value: ValueSourceDef,
195}
196
197impl SetPropertyStepDef {
198 pub fn literal(key: impl Into<String>, value: impl Into<String>) -> Self {
199 Self {
200 key: key.into(),
201 value: ValueSourceDef::Literal(serde_json::Value::String(value.into())),
202 }
203 }
204}
205
206#[derive(Debug, Clone, PartialEq)]
207pub struct SetBodyStepDef {
208 pub value: ValueSourceDef,
209}
210
211#[derive(Debug, Clone, PartialEq)]
212pub struct FilterStepDef {
213 pub predicate: LanguageExpressionDef,
214 pub steps: Vec<DeclarativeStep>,
215}
216
217#[derive(Debug, Clone, PartialEq, Eq)]
218pub struct FunctionStepDef {
219 pub runtime: String,
220 pub source: String,
221 pub timeout_ms: Option<u64>,
222}
223
224#[derive(Debug, Clone, PartialEq)]
225pub struct WhenStepDef {
226 pub predicate: LanguageExpressionDef,
227 pub steps: Vec<DeclarativeStep>,
228}
229
230#[derive(Debug, Clone, PartialEq)]
231pub struct ChoiceStepDef {
232 pub whens: Vec<WhenStepDef>,
233 pub otherwise: Option<Vec<DeclarativeStep>>,
234}
235
236#[derive(Debug, Clone, PartialEq)]
237pub enum SplitExpressionDef {
238 BodyLines,
239 BodyJsonArray,
240 Language(LanguageExpressionDef),
241 Stream(StreamSplitConfig),
242}
243
244#[derive(Debug, Clone, PartialEq, Eq)]
245pub enum SplitAggregationDef {
246 LastWins,
247 CollectAll,
248 Original,
249}
250
251#[derive(Debug, Clone, PartialEq)]
252pub struct SplitStepDef {
253 pub expression: SplitExpressionDef,
254 pub aggregation: SplitAggregationDef,
255 pub parallel: bool,
256 pub parallel_limit: Option<usize>,
257 pub stop_on_exception: bool,
258 pub steps: Vec<DeclarativeStep>,
259}
260
261#[derive(Debug, Clone, PartialEq, Eq)]
262pub enum AggregateStrategyDef {
263 CollectAll,
264}
265
266#[derive(Debug, Clone, PartialEq)]
267pub struct AggregateStepDef {
268 pub header: String,
269 pub correlation_key: Option<String>,
270 pub completion_size: Option<usize>,
271 pub completion_timeout_ms: Option<u64>,
272 pub completion_predicate: Option<LanguageExpressionDef>,
273 pub strategy: AggregateStrategyDef,
274 pub max_buckets: Option<usize>,
275 pub bucket_ttl_ms: Option<u64>,
276 pub force_completion_on_stop: Option<bool>,
277 pub discard_on_timeout: Option<bool>,
278}
279
280#[derive(Debug, Clone, PartialEq, Eq)]
281pub struct WireTapStepDef {
282 pub uri: String,
283}
284
285#[derive(Debug, Clone, PartialEq, Eq)]
286pub struct BeanStepDef {
287 pub name: String,
288 pub method: String,
289}
290
291impl BeanStepDef {
292 pub fn new(name: impl Into<String>, method: impl Into<String>) -> Self {
293 Self {
294 name: name.into(),
295 method: method.into(),
296 }
297 }
298}
299
300#[derive(Debug, Clone, PartialEq, Eq, Default)]
301pub enum ThrottleStrategyDef {
302 #[default]
303 Delay,
304 Reject,
305 Drop,
306}
307
308#[derive(Debug, Clone, PartialEq)]
309pub struct ThrottleStepDef {
310 pub max_requests: usize,
311 pub period_ms: u64,
312 pub strategy: ThrottleStrategyDef,
313 pub steps: Vec<DeclarativeStep>,
314}
315
316#[derive(Debug, Clone, PartialEq, Eq, Default)]
317pub enum LoadBalanceStrategyDef {
318 #[default]
319 RoundRobin,
320 Random,
321 Failover,
322 Weighted {
323 distribution_ratio: String,
324 },
325}
326
327#[derive(Debug, Clone, PartialEq)]
328pub struct LoadBalanceStepDef {
329 pub strategy: LoadBalanceStrategyDef,
330 pub steps: Vec<DeclarativeStep>,
331}
332
333#[derive(Debug, Clone, PartialEq, Eq)]
334pub struct DynamicRouterStepDef {
335 pub expression: LanguageExpressionDef,
336 pub uri_delimiter: String,
337 pub cache_size: i32,
338 pub ignore_invalid_endpoints: bool,
339 pub max_iterations: usize,
340}
341
342#[derive(Debug, Clone, PartialEq, Eq)]
343pub struct RoutingSlipStepDef {
344 pub expression: LanguageExpressionDef,
345 pub uri_delimiter: String,
346 pub cache_size: i32,
347 pub ignore_invalid_endpoints: bool,
348}
349
350#[derive(Debug, Clone, PartialEq, Eq)]
351pub struct RecipientListStepDef {
352 pub expression: LanguageExpressionDef,
353 pub delimiter: String,
354 pub parallel: bool,
355 pub parallel_limit: Option<usize>,
356 pub stop_on_exception: bool,
357 pub aggregation: MulticastAggregationDef,
358}
359
360#[derive(Debug, Clone, PartialEq, Eq)]
361pub enum MulticastAggregationDef {
362 LastWins,
363 CollectAll,
364 Original,
365}
366
367#[derive(Debug, Clone, PartialEq)]
368pub struct MulticastStepDef {
369 pub steps: Vec<DeclarativeStep>,
370 pub parallel: bool,
371 pub parallel_limit: Option<usize>,
372 pub stop_on_exception: bool,
373 pub timeout_ms: Option<u64>,
374 pub aggregation: MulticastAggregationDef,
375}
376
377#[derive(Debug, Clone, PartialEq, Eq)]
378pub struct ScriptStepDef {
379 pub expression: LanguageExpressionDef,
380}
381
382#[derive(Debug, Clone, PartialEq, Eq)]
383pub enum BodyTypeDef {
384 Text,
385 Json,
386 Bytes,
387 Xml,
388 Empty,
389}
390
391#[derive(Debug, Clone, PartialEq)]
392pub struct DataFormatDef {
393 pub format: String,
394 pub schema: Option<serde_json::Value>,
398 pub config: Option<serde_json::Value>,
401}
402
403#[derive(Debug, Clone, PartialEq, Eq)]
404pub struct DelayStepDef {
405 pub delay_ms: u64,
406 pub dynamic_header: Option<String>,
407}
408
409#[derive(Debug, Clone, PartialEq)]
410pub struct LoopStepDef {
411 pub count: Option<usize>,
412 pub while_predicate: Option<LanguageExpressionDef>,
413 pub steps: Vec<DeclarativeStep>,
414 pub max_iterations: Option<usize>,
415}
416
417#[derive(Debug, Clone, PartialEq, Eq)]
418pub struct StreamCacheStepDef {
419 pub threshold: Option<usize>,
420}
421
422#[derive(Debug, Clone, PartialEq, Eq)]
423pub struct ValidateStepDef {
424 pub predicate: LanguageExpressionDef,
425}
426
427#[derive(Debug, Clone, PartialEq, Eq)]
431pub struct ClaimCheckStepDef {
432 pub repository: String,
434 pub operation: String,
436 pub key: LanguageExpressionDef,
438 pub filter: Option<String>,
440}
441
442#[derive(Debug, Clone, PartialEq)]
447pub struct IdempotentConsumerStepDef {
448 pub repository: String,
450 pub expression: LanguageExpressionDef,
452 pub steps: Vec<DeclarativeStep>,
454 pub eager: Option<bool>,
457 pub remove_on_failure: Option<bool>,
460}
461
462#[derive(Debug, Clone, PartialEq)]
467pub struct CacheStepDef {
468 pub repository: Option<String>,
470 pub key: LanguageExpressionDef,
472 pub ttl: Option<String>,
474 pub max_entry_bytes: Option<usize>,
476 pub on_miss: Vec<DeclarativeStep>,
478}
479
480#[derive(Debug, Clone, PartialEq, Eq)]
484pub struct CacheInvalidateStepDef {
485 pub repository: Option<String>,
487 pub key: LanguageExpressionDef,
489}
490
491#[derive(Debug, Clone, PartialEq, Eq)]
495pub struct CachePeekStaleStepDef {
496 pub repository: Option<String>,
498 pub key: LanguageExpressionDef,
500}
501
502#[derive(Debug, Clone, PartialEq, Eq)]
506pub struct SamplingStepDef {
507 pub period: usize,
509}
510
511#[derive(Debug, Clone, PartialEq, Eq)]
516pub struct SortStepDef {
517 pub expression: LanguageExpressionDef,
519 pub reverse: bool,
521}
522
523#[derive(Debug, Clone, PartialEq, Eq)]
527pub struct ResequenceStepDef {
528 pub mode: ResequenceModeDef,
529}
530
531#[derive(Debug, Clone, PartialEq, Eq)]
533pub enum ResequenceModeDef {
534 Batch {
535 correlation: String,
536 sort: String,
537 completion: camel_api::resequencer::BatchCompletion,
538 },
539 Stream {
540 sequence: String,
541 capacity: usize,
542 gap_timeout: u64,
543 on_gap: camel_api::resequencer::GapPolicy,
544 on_capacity_exceeded: camel_api::resequencer::CapacityPolicy,
545 dedup: bool,
546 },
547}
548
549#[derive(Debug, Clone, PartialEq, Eq)]
550pub struct EnrichStepDef {
551 pub uri: String,
552 pub strategy: Option<String>,
553 pub timeout_ms: Option<u64>,
554}
555
556#[derive(Debug, Clone, PartialEq)]
557pub struct DoTryCatchClauseDef {
558 pub exception: Option<Vec<String>>,
559 pub when: Option<LanguageExpressionDef>,
560 pub on_when: Option<LanguageExpressionDef>,
561 pub disposition: camel_api::error_handler::ExceptionDisposition,
562 pub steps: Vec<DeclarativeStep>,
563}
564
565#[derive(Debug, Clone, PartialEq)]
566pub struct DoTryFinallyDef {
567 pub on_when: Option<LanguageExpressionDef>,
568 pub steps: Vec<DeclarativeStep>,
569}
570
571#[derive(Debug, Clone, PartialEq)]
572pub enum DeclarativeStep {
573 To(ToStepDef),
574 SetHeader(SetHeaderStepDef),
575 SetHeaderIfAbsent(SetHeaderStepDef),
576 SetProperty(SetPropertyStepDef),
577 SetBody(SetBodyStepDef),
578 ConvertBodyTo(BodyTypeDef),
579 DynamicRouter(DynamicRouterStepDef),
580 Filter(FilterStepDef),
581 Function(FunctionStepDef),
582 LoadBalance(LoadBalanceStepDef),
583 Log(LogStepDef),
584 Choice(ChoiceStepDef),
585 Split(SplitStepDef),
586 Aggregate(AggregateStepDef),
587 WireTap(WireTapStepDef),
588 Multicast(MulticastStepDef),
589 RoutingSlip(RoutingSlipStepDef),
590 RecipientList(RecipientListStepDef),
591 Stop,
592 Throttle(ThrottleStepDef),
593 Script(ScriptStepDef),
594 StreamCache(StreamCacheStepDef),
595 Marshal(DataFormatDef),
596 Unmarshal(DataFormatDef),
597 Validate(ValidateStepDef),
598 Bean(BeanStepDef),
599 Delay(DelayStepDef),
600 Loop(LoopStepDef),
601 Enrich(EnrichStepDef),
602 PollEnrich(EnrichStepDef),
603 IdempotentConsumer(IdempotentConsumerStepDef),
604 Cache(CacheStepDef),
605 CacheInvalidate(CacheInvalidateStepDef),
606 CachePeekStale(CachePeekStaleStepDef),
607 ClaimCheck(ClaimCheckStepDef),
608 Sampling(SamplingStepDef),
609 Sort(SortStepDef),
610 Resequence(ResequenceStepDef),
611 DoTry {
612 steps: Vec<DeclarativeStep>,
613 catch: Vec<DoTryCatchClauseDef>,
614 finally: Option<DoTryFinallyDef>,
615 },
616}
617
618impl DeclarativeStep {
619 pub fn kind(&self) -> crate::contract::DeclarativeStepKind {
620 match self {
621 DeclarativeStep::To(_) => crate::contract::DeclarativeStepKind::To,
622 DeclarativeStep::Log(_) => crate::contract::DeclarativeStepKind::Log,
623 DeclarativeStep::SetHeader(_) => crate::contract::DeclarativeStepKind::SetHeader,
624 DeclarativeStep::SetHeaderIfAbsent(_) => {
625 crate::contract::DeclarativeStepKind::SetHeaderIfAbsent
626 }
627 DeclarativeStep::SetProperty(_) => crate::contract::DeclarativeStepKind::SetProperty,
628 DeclarativeStep::SetBody(_) => crate::contract::DeclarativeStepKind::SetBody,
629 DeclarativeStep::ConvertBodyTo(_) => {
630 crate::contract::DeclarativeStepKind::ConvertBodyTo
631 }
632 DeclarativeStep::DynamicRouter(_) => {
633 crate::contract::DeclarativeStepKind::DynamicRouter
634 }
635 DeclarativeStep::Filter(_) => crate::contract::DeclarativeStepKind::Filter,
636 DeclarativeStep::Function(_) => crate::contract::DeclarativeStepKind::Function,
637 DeclarativeStep::LoadBalance(_) => crate::contract::DeclarativeStepKind::LoadBalance,
638 DeclarativeStep::Choice(_) => crate::contract::DeclarativeStepKind::Choice,
639 DeclarativeStep::Split(_) => crate::contract::DeclarativeStepKind::Split,
640 DeclarativeStep::Aggregate(_) => crate::contract::DeclarativeStepKind::Aggregate,
641 DeclarativeStep::WireTap(_) => crate::contract::DeclarativeStepKind::WireTap,
642 DeclarativeStep::Multicast(_) => crate::contract::DeclarativeStepKind::Multicast,
643 DeclarativeStep::RoutingSlip(_) => crate::contract::DeclarativeStepKind::RoutingSlip,
644 DeclarativeStep::RecipientList(_) => {
645 crate::contract::DeclarativeStepKind::RecipientList
646 }
647 DeclarativeStep::Stop => crate::contract::DeclarativeStepKind::Stop,
648 DeclarativeStep::Throttle(_) => crate::contract::DeclarativeStepKind::Throttle,
649 DeclarativeStep::Script(_) => crate::contract::DeclarativeStepKind::Script,
650 DeclarativeStep::StreamCache(_) => crate::contract::DeclarativeStepKind::StreamCache,
651 DeclarativeStep::Marshal(_) => crate::contract::DeclarativeStepKind::Marshal,
652 DeclarativeStep::Unmarshal(_) => crate::contract::DeclarativeStepKind::Unmarshal,
653 DeclarativeStep::Validate(_) => crate::contract::DeclarativeStepKind::Validate,
654 DeclarativeStep::Bean(_) => crate::contract::DeclarativeStepKind::Bean,
655 DeclarativeStep::Delay(_) => crate::contract::DeclarativeStepKind::Delay,
656 DeclarativeStep::Loop(_) => crate::contract::DeclarativeStepKind::Loop,
657 DeclarativeStep::Enrich(_) => crate::contract::DeclarativeStepKind::Enrich,
658 DeclarativeStep::PollEnrich(_) => crate::contract::DeclarativeStepKind::PollEnrich,
659 DeclarativeStep::IdempotentConsumer(_) => {
660 crate::contract::DeclarativeStepKind::IdempotentConsumer
661 }
662 DeclarativeStep::Cache(_) => crate::contract::DeclarativeStepKind::Cache,
663 DeclarativeStep::CacheInvalidate(_) => {
664 crate::contract::DeclarativeStepKind::CacheInvalidate
665 }
666 DeclarativeStep::CachePeekStale(_) => {
667 crate::contract::DeclarativeStepKind::CachePeekStale
668 }
669 DeclarativeStep::ClaimCheck(_) => crate::contract::DeclarativeStepKind::ClaimCheck,
670 DeclarativeStep::Sampling(_) => crate::contract::DeclarativeStepKind::Sampling,
671 DeclarativeStep::Sort(_) => crate::contract::DeclarativeStepKind::Sort,
672 DeclarativeStep::Resequence(_) => crate::contract::DeclarativeStepKind::Resequence,
673 DeclarativeStep::DoTry { .. } => crate::contract::DeclarativeStepKind::DoTry,
674 }
675 }
676}
677
678#[cfg(test)]
679mod tests {
680 use super::*;
681
682 #[test]
683 fn to_step_def_new() {
684 let def = ToStepDef::new("direct:a");
685 assert_eq!(def.uri, "direct:a");
686 }
687
688 #[test]
689 fn log_step_def_info() {
690 let def = LogStepDef::info("hello");
691 assert_eq!(def.level, LogLevelDef::Info);
692 match def.message {
693 ValueSourceDef::Literal(v) => assert_eq!(v, serde_json::Value::String("hello".into())),
694 _ => panic!("expected literal"),
695 }
696 }
697
698 #[test]
699 fn set_header_literal() {
700 let def = SetHeaderStepDef::literal("key", "value");
701 assert_eq!(def.key, "key");
702 match def.value {
703 ValueSourceDef::Literal(v) => assert_eq!(v, serde_json::Value::String("value".into())),
704 _ => panic!("expected literal"),
705 }
706 }
707
708 #[test]
709 fn bean_step_def_new() {
710 let def = BeanStepDef::new("myBean", "process");
711 assert_eq!(def.name, "myBean");
712 assert_eq!(def.method, "process");
713 }
714
715 #[test]
716 fn throttle_strategy_default() {
717 assert_eq!(ThrottleStrategyDef::default(), ThrottleStrategyDef::Delay);
718 }
719
720 #[test]
721 fn load_balance_strategy_default() {
722 assert_eq!(
723 LoadBalanceStrategyDef::default(),
724 LoadBalanceStrategyDef::RoundRobin
725 );
726 }
727
728 #[test]
729 fn concurrency_variants_equality() {
730 assert_eq!(
731 DeclarativeConcurrency::Sequential,
732 DeclarativeConcurrency::Sequential
733 );
734 assert_ne!(
735 DeclarativeConcurrency::Sequential,
736 DeclarativeConcurrency::Concurrent { max: None }
737 );
738 }
739
740 #[test]
741 fn body_type_variants() {
742 assert_eq!(BodyTypeDef::Text, BodyTypeDef::Text);
743 assert_ne!(BodyTypeDef::Text, BodyTypeDef::Json);
744 }
745
746 #[test]
747 fn data_format_def() {
748 let def = DataFormatDef {
749 format: "protobuf".into(),
750 schema: None,
751 config: None,
752 };
753 assert_eq!(def.format, "protobuf");
754 assert!(def.schema.is_none());
755 }
756
757 #[test]
758 fn stream_cache_step_def() {
759 let def = StreamCacheStepDef {
760 threshold: Some(1024),
761 };
762 assert_eq!(def.threshold, Some(1024));
763 }
764
765 #[test]
766 fn delay_step_def() {
767 let def = DelayStepDef {
768 delay_ms: 500,
769 dynamic_header: Some("X-Delay".into()),
770 };
771 assert_eq!(def.delay_ms, 500);
772 assert_eq!(def.dynamic_header.as_deref(), Some("X-Delay"));
773 }
774
775 #[test]
776 fn circuit_breaker_def() {
777 let cb = DeclarativeCircuitBreaker {
778 failure_threshold: 3,
779 open_duration_ms: 5000,
780 };
781 assert_eq!(cb.failure_threshold, 3);
782 assert_eq!(cb.open_duration_ms, 5000);
783 }
784}