Skip to main content

dope_runtime/topology/
worker.rs

1use dope_core::driver::storage;
2
3use crate::{
4    executor::{self, boot, session},
5    topology::{self, app, lending},
6};
7
8/// Generative worker scope after storage construction and before application install.
9pub struct Worker<'scope, 'life: 'scope, 'p: 'life, 'd: 'p, S: storage::Plan + 'd, I: 'd, Q: 'd> {
10    pub(super) session: session::Scope<'scope, 'life, 'p, 'd, S, Q>,
11    pub(super) installer: I,
12}
13
14impl<'scope, 'life: 'scope, 'p: 'life, 'd: 'p, S: storage::Plan + 'd, I: 'd, Q: 'd>
15    Worker<'scope, 'life, 'p, 'd, S, I, Q>
16{
17    pub(crate) const fn new(
18        session: session::Scope<'scope, 'life, 'p, 'd, S, Q>,
19        setup: I,
20    ) -> Self {
21        Self {
22            session,
23            installer: setup,
24        }
25    }
26}
27
28impl<'scope, 'life: 'scope, 'p: 'life, 'd: 'p, S, I, Q> Worker<'scope, 'life, 'p, 'd, S, I, Q>
29where
30    S: storage::Plan + 'd,
31    I: 'd,
32    Q: executor::Startup + 'd,
33{
34    /// Borrows storage from the exact prepared domain.
35    pub fn storage(&self) -> &'life S::Output<'p, 'd> {
36        self.session.storage()
37    }
38
39    /// Consumes the retained specification in one lexical lending scope.
40    pub fn lend<R>(
41        mut self,
42        compose: impl FnOnce(I, &mut lending::Stage<'_, 'scope, 'life, 'p, 'd, S, Q>) -> R,
43    ) -> R {
44        let mut stage = lending::Stage::new(&mut self.session);
45        compose(self.installer, &mut stage)
46    }
47
48    /// Runs the retained installer and consumer inside their storage loans.
49    pub fn with<N, R, E>(mut self, next: N) -> Result<R, E>
50    where
51        I: for<'stage> lending::Installer<
52                lending::Stage<'stage, 'scope, 'life, 'p, 'd, S, Q>,
53                N,
54                Output = R,
55                Error = E,
56            >,
57    {
58        let mut stage = lending::Stage::new(&mut self.session);
59        self.installer.install(&mut stage, next)
60    }
61
62    /// Drives a yielding installation before publishing the resulting application.
63    /// Rejects existing native work and cancels the unpolled root on admission failure.
64    pub fn install_with<A, R, E>(
65        mut self,
66        install: impl FnOnce(I, &topology::Boot<'_, 'scope, 'life, 'p, 'd, S, Q>) -> R,
67    ) -> Result<app::Application<'scope, 'life, 'p, 'd, S, A, Q>, topology::InstallError<E>>
68    where
69        A: executor::raw::App<'d>,
70        R: boot::Root<'d, Output = Result<A, E>>,
71    {
72        let root = {
73            let stage = topology::Boot::new(&self.session);
74            install(self.installer, &stage)
75        };
76        let app = self
77            .session
78            .drive(root)
79            .map_err(topology::InstallError::Drive)?
80            .map_err(topology::InstallError::Install)?;
81        Ok(app::Application {
82            session: self.session,
83            app,
84        })
85    }
86}
87
88impl<'scope, 'life: 'scope, 'p: 'life, 'd: 'p, S, I, Q> Worker<'scope, 'life, 'p, 'd, S, I, Q>
89where
90    S: storage::Plan + 'd,
91    I: topology::Installer<S> + 'd,
92    Q: executor::Startup + 'd,
93{
94    pub fn install(
95        mut self,
96    ) -> Result<app::Application<'scope, 'life, 'p, 'd, S, I::App<'life, 'p, 'd>, Q>, I::Error>
97    {
98        let app = {
99            let mut stage = topology::Stage::new(&mut self.session);
100            self.installer.install(&mut stage)?
101        };
102        Ok(app::Application {
103            session: self.session,
104            app,
105        })
106    }
107}