1use crate::{
2 AsState, AsTag, KvAssoc, State, StateEvent,
3 handle::{ArcHandle, AsHandle, Handle, StateChangeError as HandleStateChangeError},
4 reader::Reader,
5 source::Source,
6};
7use async_trait::async_trait;
8use dashmap::DashMap;
9use itertools::Itertools;
10use state_m_macro::*;
11use std::{
12 fmt::{self, Debug, Display},
13 ops::Deref,
14 pin::Pin,
15 sync::Arc,
16};
17use thiserror::Error;
18use tracing::instrument;
19
20#[derive(Clone)]
23pub struct StateMachine<K>(Arc<DashMap<K, (String, Box<dyn AsHandle>)>>)
24where
25 K: AsTag;
26
27impl<K> Debug for StateMachine<K>
28where
29 K: AsTag,
30{
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 for item in self.iter() {
33 let (_, (l, h)) = item.pair();
34 write!(f, "{:<20} | {:?}\n", l, h.debug_state())?
35 }
36 Ok(())
37 }
38}
39
40impl<K> Default for StateMachine<K>
41where
42 K: AsTag,
43{
44 fn default() -> Self {
45 Self(Default::default())
46 }
47}
48
49impl<K> Deref for StateMachine<K>
50where
51 K: AsTag,
52{
53 type Target = Arc<DashMap<K, (String, Box<dyn AsHandle>)>>;
54
55 fn deref(&self) -> &Self::Target {
56 &self.0
57 }
58}
59
60impl<K> StateMachine<K>
61where
62 K: 'static + AsTag,
63{
64 fn get_handle<T>(&self, tag: T) -> Result<ArcHandle<T::Value>, GetHandleError<K>>
65 where
66 T: Clone + Debug + Into<K> + KvAssoc,
67 T::Value: AsState + Send + Sync,
68 {
69 let k = tag.clone().into();
70 match self.get(&k) {
71 Some(v) => match v.value().1.downcast_ref::<ArcHandle<T::Value>>() {
72 Some(h) => Ok(h.clone()),
73 None => Err(GetHandleError::TypeNotMatch),
74 },
75 None => Err(GetHandleError::HandleNotExist(tag.into())),
76 }
77 }
78}
79
80impl<K> StateMachine<K>
81where
82 K: 'static + AsTag,
83{
84 pub async fn add_source<T>(&self, tag: T, capacity: usize) -> Result<(), AddHandleError<K>>
86 where
87 T: 'static + Clone + Debug + Display + Into<K> + KvAssoc + Send + Sync,
88 T::Value: 'static + AsState + Send + Sync,
89 {
90 let k = tag.clone().into();
91 if self.contains_key(&k) {
92 return Err(AddHandleError::AlreadyExist(tag.into()));
93 }
94 let h = ArcHandle(Arc::new(Handle::from_source(Source::<T::Value>::new(
95 capacity,
96 ))));
97 h.init(tag.clone()).await;
98 self.insert(k, (tag.to_string(), Box::new(h)));
99 Ok(())
100 }
101
102 pub async fn add_reader<T>(
104 &self,
105 tag: T,
106 reader: Reader<T::Value>,
107 ) -> Result<(), AddHandleError<K>>
108 where
109 T: 'static + Clone + Debug + Display + Into<K> + KvAssoc + Send + Sync,
110 T::Value: 'static + AsState + Send + Sync,
111 {
112 let k = tag.clone().into();
113 if self.contains_key(&k) {
114 return Err(AddHandleError::AlreadyExist(tag.into()));
115 }
116 if reader.is_closed() {
117 return Err(AddHandleError::ChannelClosed);
118 }
119 let h = ArcHandle(Arc::new(Handle::from_reader(reader)));
120 h.init(tag.clone()).await;
121 self.insert(k, (tag.to_string(), Box::new(h)));
122 Ok(())
123 }
124
125 pub fn del_handle<T>(&self, tag: &T) -> Result<bool, GetHandleError<K>>
127 where
128 T: 'static + Clone + Debug + Into<K> + KvAssoc,
129 T::Value: AsState + Send + Sync,
130 {
131 match self.remove(&tag.clone().into()) {
132 Some((_, v)) => match v.1.downcast_ref::<ArcHandle<T::Value>>() {
133 Some(h) => {
134 h.close();
135 Ok(true)
136 }
137 None => Err(GetHandleError::TypeNotMatch),
138 },
139 None => Ok(false),
140 }
141 }
142
143 pub fn has_handle<T>(&self, tag: &T) -> bool
145 where
146 T: Clone + Into<K>,
147 {
148 self.contains_key(&tag.clone().into())
149 }
150
151 pub fn reader<T>(&self, tag: T) -> Result<Reader<T::Value>, GetHandleError<K>>
152 where
153 T: Clone + Debug + Into<K> + KvAssoc,
154 T::Value: AsState + Send + Sync,
155 {
156 Ok(self.get_handle(tag)?.reader())
157 }
158
159 pub fn value<T>(&self, tag: T) -> Result<T::Value, GetHandleError<K>>
160 where
161 T: Clone + Debug + Into<K> + KvAssoc,
162 T::Value: 'static + AsState + Send + Sync,
163 {
164 Ok(self.get_handle(tag)?.value())
165 }
166
167 pub fn state<T>(&self, tag: T) -> Result<State<T::Value>, GetHandleError<K>>
168 where
169 T: Clone + Debug + Into<K> + KvAssoc,
170 T::Value: 'static + AsState + Send + Sync,
171 {
172 Ok(self.get_handle(tag)?.state())
173 }
174
175 pub async fn touch<T>(&self, tag: T) -> Result<(), StateChangeError<T, K>>
176 where
177 T: Clone + Debug + Into<K> + KvAssoc,
178 T::Value: 'static + AsState + Send + Sync,
179 {
180 Ok(self.get_handle(tag)?.touch().await?)
181 }
182
183 pub async fn wait_touch<T>(&self, tag: T) -> Result<(), StateChangeError<T, K>>
184 where
185 T: Clone + Debug + Into<K> + KvAssoc,
186 T::Value: 'static + AsState + Send + Sync,
187 {
188 Ok(self.get_handle(tag)?.wait_touch().await?)
189 }
190
191 pub async fn alter<T>(&self, tag: T, s: T::Value) -> Result<(), StateChangeError<T, K>>
192 where
193 T: Clone + Debug + Into<K> + KvAssoc,
194 T::Value: 'static + AsState + Send + Sync,
195 {
196 Ok(self.get_handle(tag)?.alter(s).await?)
197 }
198
199 pub async fn wait_alter<T>(&self, tag: T, s: T::Value) -> Result<(), StateChangeError<T, K>>
200 where
201 T: Clone + Debug + Into<K> + KvAssoc,
202 T::Value: 'static + AsState + Send + Sync,
203 {
204 Ok(self.get_handle(tag)?.wait_alter(s).await?)
205 }
206
207 pub async fn amend<T>(
208 &self,
209 tag: T,
210 f: impl FnOnce(T::Value) -> T::Value,
211 ) -> Result<(), StateChangeError<T, K>>
212 where
213 T: Clone + Debug + Into<K> + KvAssoc,
214 T::Value: 'static + AsState + Send + Sync,
215 {
216 Ok(self.get_handle(tag)?.amend(f).await?)
217 }
218
219 pub async fn wait_amend<T>(
220 &self,
221 tag: T,
222 f: impl FnOnce(T::Value) -> T::Value,
223 ) -> Result<(), StateChangeError<T, K>>
224 where
225 T: Clone + Debug + Into<K> + KvAssoc,
226 T::Value: 'static + AsState + Send + Sync,
227 {
228 Ok(self.get_handle(tag)?.wait_amend(f).await?)
229 }
230}
231
232#[derive(Clone, Debug)]
234pub enum StateChange<T>
235where
236 T: KvAssoc,
237 T::Value: AsState + Send + Sync,
238{
239 Change(State<T::Value>, State<T::Value>),
243 UnChange(State<T::Value>),
246}
247
248impl<T> StateChange<T>
249where
250 T: KvAssoc,
251 T::Value: AsState + Send + Sync,
252{
253 pub fn cur(&self) -> State<T::Value> {
254 match self {
255 StateChange::Change(v, _) => v.clone(),
256 StateChange::UnChange(v) => v.clone(),
257 }
258 }
259
260 pub fn old(&self) -> State<T::Value> {
261 match self {
262 StateChange::Change(_, v) => v.clone(),
263 StateChange::UnChange(v) => v.clone(),
264 }
265 }
266}
267
268impl<K> StateMachine<K>
269where
270 K: 'static + AsTag,
271{
272 sm_watch!(1);
273 sm_watch!(2);
274 sm_watch!(3);
275 sm_watch!(4);
276 sm_watch!(5);
277 sm_watch!(6);
278 sm_watch!(7);
279 sm_watch!(8);
280 sm_watch!(9);
281 sm_watch!(10);
282
283 sm_merge_reader!(2);
284 sm_merge_reader!(3);
285 sm_merge_reader!(4);
286 sm_merge_reader!(5);
287 sm_merge_reader!(6);
288 sm_merge_reader!(7);
289 sm_merge_reader!(8);
290 sm_merge_reader!(9);
291 sm_merge_reader!(10);
292
293 sm_split_reader!(2);
294 sm_split_reader!(3);
295 sm_split_reader!(4);
296 sm_split_reader!(5);
297 sm_split_reader!(6);
298 sm_split_reader!(7);
299 sm_split_reader!(8);
300 sm_split_reader!(9);
301 sm_split_reader!(10);
302}
303
304pub trait HasStateMachine {
305 type K: AsTag;
306
307 fn state_machine(&self) -> &StateMachine<Self::K>;
308}
309
310#[async_trait]
311pub trait UseStateMachine: HasStateMachine {
312 async fn add_source<T>(&self, tag: T, capacity: usize) -> Result<(), AddHandleError<Self::K>>
316 where
317 T: 'static + Clone + Debug + Display + Into<Self::K> + KvAssoc + Send + Sync,
318 T::Value: 'static + AsState + Send + Sync;
319
320 async fn add_reader<T>(
324 &self,
325 tag: T,
326 reader: Reader<T::Value>,
327 ) -> Result<(), AddHandleError<Self::K>>
328 where
329 T: 'static + Clone + Debug + Display + Into<Self::K> + KvAssoc + Send + Sync,
330 T::Value: 'static + AsState + Send + Sync;
331
332 fn del_handle<T>(&self, tag: &T) -> Result<bool, GetHandleError<Self::K>>
335 where
336 T: 'static + Clone + Debug + Into<Self::K> + KvAssoc,
337 T::Value: AsState + Send + Sync;
338
339 fn has_handle<T>(&self, tag: &T) -> bool
342 where
343 T: Clone + Into<Self::K>;
344
345 fn reader<T>(&self, tag: T) -> Result<Reader<T::Value>, GetHandleError<Self::K>>
348 where
349 T: Clone + Debug + Into<Self::K> + KvAssoc,
350 T::Value: AsState + Send + Sync;
351
352 fn value<T>(&self, tag: T) -> Result<T::Value, GetHandleError<Self::K>>
355 where
356 T: 'static + Clone + Debug + Into<Self::K> + KvAssoc + Send + Sync,
357 T::Value: 'static + AsState + Send + Sync;
358
359 fn state<T>(&self, tag: T) -> Result<State<T::Value>, GetHandleError<Self::K>>
362 where
363 T: 'static + Clone + Debug + Into<Self::K> + KvAssoc + Send + Sync,
364 T::Value: 'static + AsState + Send + Sync;
365
366 async fn touch<T>(&self, tag: T) -> Result<(), StateChangeError<T, Self::K>>
369 where
370 T: 'static + Clone + Debug + Into<Self::K> + KvAssoc + Send + Sync,
371 T::Value: 'static + AsState + Send + Sync;
372
373 async fn wait_touch<T>(&self, tag: T) -> Result<(), StateChangeError<T, Self::K>>
376 where
377 T: 'static + Clone + Debug + Into<Self::K> + KvAssoc + Send + Sync,
378 T::Value: 'static + AsState + Send + Sync;
379
380 async fn alter<T>(&self, tag: T, s: T::Value) -> Result<(), StateChangeError<T, Self::K>>
383 where
384 T: 'static + Clone + Debug + Into<Self::K> + KvAssoc + Send + Sync,
385 T::Value: 'static + AsState + Send + Sync;
386
387 async fn wait_alter<T>(&self, tag: T, s: T::Value) -> Result<(), StateChangeError<T, Self::K>>
390 where
391 T: 'static + Clone + Debug + Into<Self::K> + KvAssoc + Send + Sync,
392 T::Value: 'static + AsState + Send + Sync;
393
394 async fn amend<T>(
397 &self,
398 tag: T,
399 f: impl FnOnce(T::Value) -> T::Value + Send,
400 ) -> Result<(), StateChangeError<T, Self::K>>
401 where
402 T: 'static + Clone + Debug + Into<Self::K> + KvAssoc + Send + Sync,
403 T::Value: 'static + AsState + Send + Sync;
404
405 async fn wait_amend<T>(
408 &self,
409 tag: T,
410 f: impl FnOnce(T::Value) -> T::Value + Send,
411 ) -> Result<(), StateChangeError<T, Self::K>>
412 where
413 T: 'static + Clone + Debug + Into<Self::K> + KvAssoc + Send + Sync,
414 T::Value: 'static + AsState + Send + Sync;
415
416 watch_decl!(1);
417 watch_decl!(2);
418 watch_decl!(3);
419 watch_decl!(4);
420 watch_decl!(5);
421 watch_decl!(6);
422 watch_decl!(7);
423 watch_decl!(8);
424 watch_decl!(9);
425 watch_decl!(10);
426
427 merge_reader_decl!(2);
428 merge_reader_decl!(3);
429 merge_reader_decl!(4);
430 merge_reader_decl!(5);
431 merge_reader_decl!(6);
432 merge_reader_decl!(7);
433 merge_reader_decl!(8);
434 merge_reader_decl!(9);
435 merge_reader_decl!(10);
436
437 split_reader_decl!(2);
438 split_reader_decl!(3);
439 split_reader_decl!(4);
440 split_reader_decl!(5);
441 split_reader_decl!(6);
442 split_reader_decl!(7);
443 split_reader_decl!(8);
444 split_reader_decl!(9);
445 split_reader_decl!(10);
446}
447
448#[async_trait]
449impl<M> UseStateMachine for M
450where
451 M: 'static + HasStateMachine + Send + Sync,
452{
453 async fn add_source<T>(&self, tag: T, capacity: usize) -> Result<(), AddHandleError<Self::K>>
454 where
455 T: 'static + Clone + Debug + Display + Into<Self::K> + KvAssoc + Send + Sync,
456 T::Value: 'static + AsState + Send + Sync,
457 {
458 self.state_machine()
459 .add_source(tag.clone(), capacity)
460 .await?;
461 Ok(())
462 }
463
464 fn del_handle<T>(&self, tag: &T) -> Result<bool, GetHandleError<Self::K>>
465 where
466 T: 'static + Clone + Debug + Into<Self::K> + KvAssoc,
467 T::Value: AsState + Send + Sync,
468 {
469 self.state_machine().del_handle(tag)
470 }
471
472 fn has_handle<T>(&self, tag: &T) -> bool
473 where
474 T: Clone + Into<Self::K>,
475 {
476 self.state_machine().has_handle(tag)
477 }
478
479 fn reader<T>(&self, tag: T) -> Result<Reader<T::Value>, GetHandleError<Self::K>>
480 where
481 T: Clone + Debug + Into<Self::K> + KvAssoc,
482 T::Value: AsState + Send + Sync,
483 {
484 self.state_machine().reader(tag)
485 }
486
487 async fn add_reader<T>(
488 &self,
489 tag: T,
490 reader: Reader<T::Value>,
491 ) -> Result<(), AddHandleError<Self::K>>
492 where
493 T: 'static + Clone + Debug + Display + Into<Self::K> + KvAssoc + Send + Sync,
494 T::Value: 'static + AsState + Send + Sync,
495 {
496 self.state_machine().add_reader(tag, reader).await?;
497 Ok(())
498 }
499
500 fn value<T>(&self, tag: T) -> Result<T::Value, GetHandleError<Self::K>>
501 where
502 T: 'static + Clone + Debug + Into<Self::K> + KvAssoc + Send + Sync,
503 T::Value: 'static + AsState + Send + Sync,
504 {
505 self.state_machine().value(tag)
506 }
507
508 fn state<T>(&self, tag: T) -> Result<State<T::Value>, GetHandleError<Self::K>>
509 where
510 T: 'static + Clone + Debug + Into<Self::K> + KvAssoc + Send + Sync,
511 T::Value: 'static + AsState + Send + Sync,
512 {
513 self.state_machine().state(tag)
514 }
515
516 #[instrument(level = "trace", skip(self))]
517 async fn touch<T>(&self, tag: T) -> Result<(), StateChangeError<T, Self::K>>
518 where
519 T: 'static + Clone + Debug + Into<Self::K> + KvAssoc + Send + Sync,
520 T::Value: 'static + AsState + Send + Sync,
521 {
522 self.state_machine().touch(tag).await
523 }
524
525 #[instrument(level = "trace", skip(self))]
526 async fn wait_touch<T>(&self, tag: T) -> Result<(), StateChangeError<T, Self::K>>
527 where
528 T: 'static + Clone + Debug + Into<Self::K> + KvAssoc + Send + Sync,
529 T::Value: 'static + AsState + Send + Sync,
530 {
531 self.state_machine().wait_touch(tag).await
532 }
533
534 #[instrument(level = "trace", skip(self))]
535 async fn alter<T>(&self, tag: T, s: T::Value) -> Result<(), StateChangeError<T, Self::K>>
536 where
537 T: 'static + Clone + Debug + Into<Self::K> + KvAssoc + Send + Sync,
538 T::Value: 'static + AsState + Send + Sync,
539 {
540 self.state_machine().alter(tag, s).await
541 }
542
543 #[instrument(level = "trace", skip(self))]
544 async fn wait_alter<T>(&self, tag: T, s: T::Value) -> Result<(), StateChangeError<T, Self::K>>
545 where
546 T: 'static + Clone + Debug + Into<Self::K> + KvAssoc + Send + Sync,
547 T::Value: 'static + AsState + Send + Sync,
548 {
549 self.state_machine().wait_alter(tag, s).await
550 }
551
552 #[instrument(level = "trace", skip(self, f))]
553 async fn amend<T>(
554 &self,
555 tag: T,
556 f: impl FnOnce(T::Value) -> T::Value + Send,
557 ) -> Result<(), StateChangeError<T, Self::K>>
558 where
559 T: 'static + Clone + Debug + Into<Self::K> + KvAssoc + Send + Sync,
560 T::Value: 'static + AsState + Send + Sync,
561 {
562 self.state_machine().amend(tag, f).await
563 }
564
565 #[instrument(level = "trace", skip(self, f))]
566 async fn wait_amend<T>(
567 &self,
568 tag: T,
569 f: impl FnOnce(T::Value) -> T::Value + Send,
570 ) -> Result<(), StateChangeError<T, Self::K>>
571 where
572 T: 'static + Clone + Debug + Into<Self::K> + KvAssoc + Send + Sync,
573 T::Value: 'static + AsState + Send + Sync,
574 {
575 self.state_machine().wait_amend(tag, f).await
576 }
577
578 watch_impl!(1);
579 watch_impl!(2);
580 watch_impl!(3);
581 watch_impl!(4);
582 watch_impl!(5);
583 watch_impl!(6);
584 watch_impl!(7);
585 watch_impl!(8);
586 watch_impl!(9);
587 watch_impl!(10);
588
589 merge_reader_impl!(2);
590 merge_reader_impl!(3);
591 merge_reader_impl!(4);
592 merge_reader_impl!(5);
593 merge_reader_impl!(6);
594 merge_reader_impl!(7);
595 merge_reader_impl!(8);
596 merge_reader_impl!(9);
597 merge_reader_impl!(10);
598
599 split_reader_impl!(2);
600 split_reader_impl!(3);
601 split_reader_impl!(4);
602 split_reader_impl!(5);
603 split_reader_impl!(6);
604 split_reader_impl!(7);
605 split_reader_impl!(8);
606 split_reader_impl!(9);
607 split_reader_impl!(10);
608}
609
610#[derive(Debug, Error)]
612pub enum StateChangeError<T, K>
613where
614 T: Debug + Into<K> + KvAssoc,
615 T::Value: Default,
616 K: AsTag,
617{
618 #[error(transparent)]
619 GetHandleError(#[from] GetHandleError<K>),
620 #[error(transparent)]
621 StateChangeError(#[from] HandleStateChangeError<T::Value>),
622}
623
624#[derive(Debug, Error)]
626pub enum GetHandleError<K>
627where
628 K: AsTag,
629{
630 #[error("State handle for tag [{0:?}] not exist.")]
631 HandleNotExist(K),
632 #[error("Type of state value does not match.")]
633 TypeNotMatch,
634}
635
636#[derive(Debug, Error)]
638pub enum AddHandleError<K>
639where
640 K: AsTag,
641{
642 #[error("State handle for tag [{0:?}] already exist.")]
643 AlreadyExist(K),
644 #[error("The state channel has been closed.")]
645 ChannelClosed,
646}