fedimint_client_module/sm/
executor.rs

1use std::io::{self, Read, Write};
2use std::sync::Arc;
3use std::time::SystemTime;
4
5use fedimint_core::core::{ModuleInstanceId, OperationId};
6use fedimint_core::db::DatabaseTransaction;
7use fedimint_core::encoding::{Decodable, DecodeError, Encodable};
8use fedimint_core::module::registry::ModuleDecoderRegistry;
9use fedimint_core::{apply, async_trait_maybe_send, maybe_add_send_sync};
10
11use super::DynState;
12use crate::{AddStateMachinesResult, DynGlobalClientContext};
13
14pub type ContextGen =
15    Arc<maybe_add_send_sync!(dyn Fn(ModuleInstanceId, OperationId) -> DynGlobalClientContext)>;
16
17/// A state that is able to make progress eventually
18#[derive(Debug)]
19pub struct ActiveStateKey {
20    // TODO: remove redundant operation id from state trait
21    pub operation_id: OperationId,
22    // TODO: state being a key... seems ... risky?
23    pub state: DynState,
24}
25
26impl ActiveStateKey {
27    pub fn from_state(state: DynState) -> ActiveStateKey {
28        ActiveStateKey {
29            operation_id: state.operation_id(),
30            state,
31        }
32    }
33}
34
35impl Encodable for ActiveStateKey {
36    fn consensus_encode<W: Write>(&self, writer: &mut W) -> Result<(), io::Error> {
37        self.operation_id.consensus_encode(writer)?;
38        self.state.consensus_encode(writer)?;
39        Ok(())
40    }
41}
42
43impl Decodable for ActiveStateKey {
44    fn consensus_decode_partial<R: Read>(
45        reader: &mut R,
46        modules: &ModuleDecoderRegistry,
47    ) -> Result<Self, DecodeError> {
48        let operation_id = OperationId::consensus_decode_partial(reader, modules)?;
49        let state = DynState::consensus_decode_partial(reader, modules)?;
50
51        Ok(ActiveStateKey {
52            operation_id,
53            state,
54        })
55    }
56}
57
58#[derive(Debug, Copy, Clone, Encodable, Decodable)]
59pub struct ActiveStateMeta {
60    pub created_at: SystemTime,
61}
62
63impl ActiveStateMeta {
64    pub fn into_inactive(self) -> InactiveStateMeta {
65        InactiveStateMeta {
66            created_at: self.created_at,
67            exited_at: fedimint_core::time::now(),
68        }
69    }
70}
71
72impl Default for ActiveStateMeta {
73    fn default() -> Self {
74        Self {
75            created_at: fedimint_core::time::now(),
76        }
77    }
78}
79
80/// A past or final state of a state machine
81#[derive(Debug, Clone)]
82pub struct InactiveStateKey {
83    // TODO: remove redundant operation id from state trait
84    pub operation_id: OperationId,
85    pub state: DynState,
86}
87
88impl InactiveStateKey {
89    pub fn from_state(state: DynState) -> InactiveStateKey {
90        InactiveStateKey {
91            operation_id: state.operation_id(),
92            state,
93        }
94    }
95}
96
97impl Encodable for InactiveStateKey {
98    fn consensus_encode<W: Write>(&self, writer: &mut W) -> Result<(), std::io::Error> {
99        self.operation_id.consensus_encode(writer)?;
100        self.state.consensus_encode(writer)?;
101        Ok(())
102    }
103}
104
105impl Decodable for InactiveStateKey {
106    fn consensus_decode_partial<R: Read>(
107        reader: &mut R,
108        modules: &ModuleDecoderRegistry,
109    ) -> Result<Self, DecodeError> {
110        let operation_id = OperationId::consensus_decode_partial(reader, modules)?;
111        let state = DynState::consensus_decode_partial(reader, modules)?;
112
113        Ok(InactiveStateKey {
114            operation_id,
115            state,
116        })
117    }
118}
119
120#[derive(Debug, Copy, Clone, Decodable, Encodable)]
121pub struct InactiveStateMeta {
122    pub created_at: SystemTime,
123    pub exited_at: SystemTime,
124}
125
126#[apply(async_trait_maybe_send!)]
127pub trait IExecutor {
128    async fn get_active_states(&self) -> Vec<(DynState, ActiveStateMeta)>;
129
130    async fn add_state_machines_dbtx(
131        &self,
132        dbtx: &mut DatabaseTransaction<'_>,
133        states: Vec<DynState>,
134    ) -> AddStateMachinesResult;
135}