crb_routine/
runtime.rs

1use crate::finalizer::{BoxFinalizer, Finalizer};
2use crate::routine::Routine;
3use async_trait::async_trait;
4use crb_core::time::Duration;
5use crb_runtime::kit::{
6    Context, Controller, Failures, InteractiveRuntime, Interruptor, ManagedContext, Runtime,
7};
8
9pub struct RoutineRuntime<R: Routine> {
10    pub routine: R,
11    pub context: R::Context,
12    pub failures: Failures,
13}
14
15impl<R: Routine> RoutineRuntime<R> {
16    pub fn new(routine: R) -> Self
17    where
18        R::Context: Default,
19    {
20        Self {
21            routine,
22            context: R::Context::default(),
23            failures: Failures::default(),
24        }
25    }
26}
27
28#[async_trait]
29impl<R: Routine> InteractiveRuntime for RoutineRuntime<R> {
30    type Context = R::Context;
31
32    fn address(&self) -> <Self::Context as Context>::Address {
33        self.context.address().clone()
34    }
35}
36
37#[async_trait]
38impl<R: Routine> Runtime for RoutineRuntime<R> {
39    fn get_interruptor(&mut self) -> Interruptor {
40        self.context.session().controller().interruptor.clone()
41    }
42
43    async fn routine(&mut self) {
44        let ctx = &mut self.context;
45        let result = self.routine.routine(ctx).await;
46        self.failures.put(result);
47    }
48}
49
50pub struct RoutineSession<R: Routine> {
51    controller: Controller,
52    /// Interval between repeatable routine calls
53    interval: Duration,
54    finalizer: Option<BoxFinalizer<R::Output>>,
55}
56
57impl<R: Routine> Default for RoutineSession<R> {
58    fn default() -> Self {
59        let controller = Controller::default();
60        Self {
61            controller,
62            interval: Duration::from_secs(5),
63            finalizer: None,
64        }
65    }
66}
67
68impl<R: Routine> RoutineSession<R> {
69    /// Set repeat interval.
70    pub fn set_interval(&mut self, interval: Duration) {
71        self.interval = interval;
72    }
73
74    pub fn interval(&self) -> Duration {
75        self.interval
76    }
77
78    pub fn set_finalizer(&mut self, finalizer: impl Finalizer<R::Output>) {
79        self.finalizer = Some(Box::new(finalizer));
80    }
81
82    pub fn take_finalizer(&mut self) -> Option<BoxFinalizer<R::Output>> {
83        self.finalizer.take()
84    }
85}
86
87impl<R: Routine> Context for RoutineSession<R> {
88    // TODO: TaskAddress that uses a controller internally
89    type Address = ();
90
91    fn address(&self) -> &Self::Address {
92        &()
93    }
94}
95
96impl<R: Routine> ManagedContext for RoutineSession<R> {
97    fn controller(&mut self) -> &mut Controller {
98        &mut self.controller
99    }
100
101    fn shutdown(&mut self) {
102        self.controller.stop(false).ok();
103    }
104}
105
106pub trait RoutineContext<R: Routine>: Context {
107    fn session(&mut self) -> &mut RoutineSession<R>;
108}
109
110impl<R: Routine> RoutineContext<R> for RoutineSession<R> {
111    fn session(&mut self) -> &mut RoutineSession<R> {
112        self
113    }
114}