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#[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
70pub 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}