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
use std::collections::HashMap;

use crate::service::BridgeService;

/// Lifeline task stack, keep all running services
#[derive(Debug, Default)]
pub struct TaskStack<B: lifeline::Bus> {
    services: HashMap<String, Box<dyn BridgeService + Send + Sync>>,
    carries: Vec<lifeline::Lifeline>,
    bus: B,
}

impl<B: lifeline::Bus> TaskStack<B> {
    /// Create a task stack
    pub fn new(bus: B) -> Self {
        Self {
            services: Default::default(),
            carries: Default::default(),
            bus,
        }
    }
}

impl<B: lifeline::Bus> TaskStack<B> {
    /// Get bus reference
    pub fn bus(&self) -> &B {
        &self.bus
    }

    /// Spawn lifeline service
    pub fn spawn_service<
        S: lifeline::Service<Bus = B, Lifeline = color_eyre::Result<S>>
            + BridgeService
            + Send
            + Sync
            + 'static,
    >(
        &mut self,
    ) -> color_eyre::Result<()> {
        let type_name = std::any::type_name::<S>();
        let service = Box::new(S::spawn(&self.bus)?);
        self.services.insert(type_name.to_string(), service);
        Ok(())
    }

    /// Stop lifeline service
    pub fn stop_service<
        S: lifeline::Service<Bus = B, Lifeline = color_eyre::Result<S>> + BridgeService,
    >(
        &mut self,
    ) -> Option<Box<dyn BridgeService + Send + Sync>> {
        let type_name = std::any::type_name::<S>();
        self.services.remove(type_name)
    }

    /// Respawn lifeline service
    pub fn respawn_service<
        S: lifeline::Service<Bus = B, Lifeline = color_eyre::Result<S>>
            + BridgeService
            + Send
            + Sync
            + 'static,
    >(
        &mut self,
    ) -> color_eyre::Result<()> {
        // keep it until leave this block
        let _ = self.stop_service::<S>();
        self.spawn_service::<S>()
    }

    /// Lifeline service carry
    pub fn carry_from<CY: lifeline::Bus>(&mut self, other: &TaskStack<CY>) -> color_eyre::Result<()>
    where
        B: lifeline::Bus
            + lifeline::prelude::CarryFrom<CY, Lifeline = color_eyre::Result<lifeline::Lifeline>>,
    {
        let lifeline = self.bus.carry_from(&other.bus)?;
        self.carries.push(lifeline);
        Ok(())
    }

    // pub fn carry(&mut self, lifeline: lifeline::Lifeline) -> color_eyre::Result<()> {
    //     self.carries.push(lifeline);
    //     Ok(())
    // }
}