1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use crate::{
spawn::{spawn_task, task_name},
Bus, Lifeline,
};
use async_trait::async_trait;
use futures::Future;
use log::{debug, error};
use std::{any::TypeId, fmt::Debug};
pub trait Service: Task {
type Bus: Bus;
type Lifeline;
fn spawn(bus: &Self::Bus) -> Self::Lifeline;
}
pub trait DefaultService: Service {
fn spawn_default() -> (Self::Bus, Self::Lifeline);
}
impl<T> DefaultService for T
where
T: Service,
{
fn spawn_default() -> (Self::Bus, Self::Lifeline) {
let bus = Self::Bus::default();
let lifeline = Self::spawn(&bus);
(bus, lifeline)
}
}
pub trait CarryFrom<IntoBus: Bus>: Bus + Task + Sized {
type Lifeline;
fn carry_from(&self, from: &IntoBus) -> Self::Lifeline;
}
pub trait CarryInto<IntoBus: Bus>: Bus + Task + Sized {
type Lifeline;
fn carry_into(&self, into: &IntoBus) -> Self::Lifeline;
}
impl<F, I> CarryInto<I> for F
where
I: CarryFrom<F>,
F: Bus,
I: Bus,
{
type Lifeline = <I as CarryFrom<F>>::Lifeline;
fn carry_into(&self, into: &I) -> Self::Lifeline {
into.carry_from(self)
}
}
pub trait DefaultCarrier<FromBus: Bus>: CarryFrom<FromBus> {
fn carry_default() -> (Self, FromBus, Self::Lifeline) {
let into = Self::default();
let from = FromBus::default();
let lifeline = into.carry_from(&from);
(into, from, lifeline)
}
}
pub trait Task {
fn task<Out>(name: &str, fut: impl Future<Output = Out> + Send + 'static) -> Lifeline
where
Out: Debug + Send + 'static,
Self: Sized,
{
let service_name = task_name::<Self>(name);
spawn_task(service_name, fut)
}
fn try_task<Out>(
name: &str,
fut: impl Future<Output = anyhow::Result<Out>> + Send + 'static,
) -> Lifeline
where
Out: Debug + 'static,
Self: Sized,
{
let service_name = task_name::<Self>(name);
spawn_task(service_name.clone(), async move {
match fut.await {
Ok(val) => {
if TypeId::of::<Out>() != TypeId::of::<()>() {
debug!("OK {}: {:?}", service_name, val);
} else {
debug!("OK {}", service_name);
}
}
Err(err) => {
error!("ERR: {}: {}", service_name, err);
}
}
})
}
}
impl<T> Task for T {}