atm0s_sdn_network/base/
service.rs

1use atm0s_sdn_identity::NodeId;
2use atm0s_sdn_utils::simple_pub_type;
3use sans_io_runtime::TaskSwitcherChild;
4
5use super::ConnectionEvent;
6
7simple_pub_type!(ServiceId, u8);
8
9/// First part is Service, which is running inside the controller.
10#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
11pub enum ServiceControlActor<UserData> {
12    Controller(UserData),
13    Worker(u16, UserData),
14}
15
16#[derive(Debug, Clone)]
17pub enum ServiceSharedInput {
18    Tick(u64),
19    Connection(ConnectionEvent),
20}
21
22#[derive(Debug)]
23pub enum ServiceInput<UserData, FeaturesEvent, ServiceControl, ToController> {
24    Control(ServiceControlActor<UserData>, ServiceControl),
25    FromWorker(ToController),
26    FeatureEvent(FeaturesEvent),
27}
28
29#[derive(Debug, PartialEq, Eq)]
30pub enum ServiceOutput<UserData, FeaturesControl, ServiceEvent, ToWorker> {
31    Event(ServiceControlActor<UserData>, ServiceEvent),
32    FeatureControl(FeaturesControl),
33    BroadcastWorkers(ToWorker),
34    OnResourceEmpty,
35}
36
37pub struct ServiceCtx {
38    pub node_id: NodeId,
39    pub session: u64,
40}
41
42pub trait Service<UserData, FeaturesControl, FeaturesEvent, ServiceControl, ServiceEvent, ToController, ToWorker> {
43    fn is_service_empty(&self) -> bool;
44    fn service_id(&self) -> u8;
45    fn service_name(&self) -> &str;
46    fn on_shared_input(&mut self, _ctx: &ServiceCtx, _now: u64, _input: ServiceSharedInput);
47    fn on_input(&mut self, _ctx: &ServiceCtx, _now: u64, input: ServiceInput<UserData, FeaturesEvent, ServiceControl, ToController>);
48    fn on_shutdown(&mut self, _ctx: &ServiceCtx, _now: u64);
49    fn pop_output2(&mut self, _now: u64) -> Option<ServiceOutput<UserData, FeaturesControl, ServiceEvent, ToWorker>>;
50}
51
52impl<UserData, FeaturesControl, FeaturesEvent, ServiceControl, ServiceEvent, ToController, ToWorker> TaskSwitcherChild<ServiceOutput<UserData, FeaturesControl, ServiceEvent, ToWorker>>
53    for Box<dyn Service<UserData, FeaturesControl, FeaturesEvent, ServiceControl, ServiceEvent, ToController, ToWorker>>
54{
55    type Time = u64;
56
57    fn empty_event(&self) -> ServiceOutput<UserData, FeaturesControl, ServiceEvent, ToWorker> {
58        ServiceOutput::OnResourceEmpty
59    }
60
61    fn is_empty(&self) -> bool {
62        self.is_service_empty()
63    }
64
65    fn pop_output(&mut self, now: u64) -> Option<ServiceOutput<UserData, FeaturesControl, ServiceEvent, ToWorker>> {
66        self.pop_output2(now)
67    }
68}
69
70/// Second part is Worker, which is running inside each data plane workers.
71pub enum ServiceWorkerInput<UserData, FeaturesEvent, ServiceControl, ToWorker> {
72    Control(ServiceControlActor<UserData>, ServiceControl),
73    FromController(ToWorker),
74    FeatureEvent(FeaturesEvent),
75}
76
77pub enum ServiceWorkerOutput<UserData, FeaturesControl, FeaturesEvent, ServiceControl, ServiceEvent, ToController> {
78    ForwardControlToController(ServiceControlActor<UserData>, ServiceControl),
79    ForwardFeatureEventToController(FeaturesEvent),
80    ToController(ToController),
81    FeatureControl(FeaturesControl),
82    Event(ServiceControlActor<UserData>, ServiceEvent),
83    OnResourceEmpty,
84}
85
86pub struct ServiceWorkerCtx {
87    pub node_id: NodeId,
88}
89
90pub trait ServiceWorker<UserData, FeaturesControl, FeaturesEvent, ServiceControl, ServiceEvent, ToController, ToWorker> {
91    fn is_service_empty(&self) -> bool;
92    fn service_id(&self) -> u8;
93    fn service_name(&self) -> &str;
94    fn on_tick(&mut self, _ctx: &ServiceWorkerCtx, _now: u64, _tick_count: u64);
95    fn on_input(&mut self, _ctx: &ServiceWorkerCtx, _now: u64, input: ServiceWorkerInput<UserData, FeaturesEvent, ServiceControl, ToWorker>);
96    fn on_shutdown(&mut self, _ctx: &ServiceWorkerCtx, _now: u64);
97    fn pop_output2(&mut self, _now: u64) -> Option<ServiceWorkerOutput<UserData, FeaturesControl, FeaturesEvent, ServiceControl, ServiceEvent, ToController>>;
98}
99
100impl<UserData, FeaturesControl, FeaturesEvent, ServiceControl, ServiceEvent, ToController, ToWorker>
101    TaskSwitcherChild<ServiceWorkerOutput<UserData, FeaturesControl, FeaturesEvent, ServiceControl, ServiceEvent, ToController>>
102    for Box<dyn ServiceWorker<UserData, FeaturesControl, FeaturesEvent, ServiceControl, ServiceEvent, ToController, ToWorker>>
103{
104    type Time = u64;
105
106    fn empty_event(&self) -> ServiceWorkerOutput<UserData, FeaturesControl, FeaturesEvent, ServiceControl, ServiceEvent, ToController> {
107        ServiceWorkerOutput::OnResourceEmpty
108    }
109
110    fn is_empty(&self) -> bool {
111        self.is_service_empty()
112    }
113
114    fn pop_output(&mut self, now: u64) -> Option<ServiceWorkerOutput<UserData, FeaturesControl, FeaturesEvent, ServiceControl, ServiceEvent, ToController>> {
115        self.pop_output2(now)
116    }
117}
118
119pub trait ServiceBuilder<UserData, FeaturesControl, FeaturesEvent, ServiceControl, ServiceEvent, ToController, ToWorker>: Send + Sync {
120    fn service_id(&self) -> u8;
121    fn service_name(&self) -> &str;
122    fn discoverable(&self) -> bool {
123        true
124    }
125    fn create(&self) -> Box<dyn Service<UserData, FeaturesControl, FeaturesEvent, ServiceControl, ServiceEvent, ToController, ToWorker>>;
126    fn create_worker(&self) -> Box<dyn ServiceWorker<UserData, FeaturesControl, FeaturesEvent, ServiceControl, ServiceEvent, ToController, ToWorker>>;
127}