1use std::convert;
2
3use dope_core::driver::{life::recovery, settings, storage};
4
5use crate::{
6 executor::{self, session},
7 shutdown,
8 topology::{self, ops, recipe},
9};
10
11pub struct Prepared<S, I> {
15 domain: topology::Domain<S>,
16 installer: I,
17}
18
19impl<S, I> Prepared<S, I> {
20 pub(super) const fn new(layout: settings::Config, storage: S, setup: I) -> Self {
21 Self {
22 domain: topology::Domain::new(layout, storage),
23 installer: setup,
24 }
25 }
26
27 pub const fn layout(&self) -> settings::Config {
28 self.domain.layout()
29 }
30}
31
32impl<S, I> Prepared<S, I>
33where
34 S: storage::Direct,
35{
36 pub fn enter_local<O, R, Done>(
37 self,
38 op: O,
39 report: impl recovery::Observe,
40 finish: impl for<'owner> FnOnce(
41 Result<R, topology::EnterError<'owner, convert::Infallible, (I, O), R>>,
42 ) -> Done,
43 ) -> Done
44 where
45 O: for<'scope, 'life, 'p, 'd> ops::Operation<
46 'd,
47 topology::Worker<'scope, 'life, 'p, 'd, S, I, ()>,
48 Output = R,
49 >,
50 {
51 self.domain
52 .enter_local((self.installer, op), report, finish)
53 }
54
55 pub fn with_local<F, R, Done>(
56 self,
57 op: F,
58 report: impl recovery::Observe,
59 finish: impl for<'owner> FnOnce(
60 Result<R, topology::EnterError<'owner, convert::Infallible, (I, F), R>>,
61 ) -> Done,
62 ) -> Done
63 where
64 F: for<'scope, 'life, 'p, 'd> FnOnce(
65 topology::Worker<'scope, 'life, 'p, 'd, S, I, ()>,
66 ) -> R,
67 {
68 self.domain
69 .enter_local((self.installer, op), report, finish)
70 }
71
72 pub fn enter<C, O, R, Done>(
73 self,
74 context: C,
75 op: O,
76 report: impl recovery::Observe,
77 finish: impl for<'owner> FnOnce(
78 Result<R, topology::EnterError<'owner, convert::Infallible, (I, O), R, C::Shutdown>>,
79 ) -> Done,
80 ) -> Done
81 where
82 C: executor::Build,
83 O: for<'scope, 'life, 'p, 'd> ops::Operation<
84 'd,
85 topology::Worker<'scope, 'life, 'p, 'd, S, I, C::Shutdown>,
86 Output = R,
87 >,
88 {
89 self.domain
90 .enter(context, (self.installer, op), report, finish)
91 }
92
93 pub fn enter_with<C, F, R, Done>(
94 self,
95 context: C,
96 op: F,
97 report: impl recovery::Observe,
98 finish: impl for<'owner> FnOnce(
99 Result<R, topology::EnterError<'owner, convert::Infallible, (I, F), R, C::Shutdown>>,
100 ) -> Done,
101 ) -> Done
102 where
103 C: executor::Build,
104 F: for<'scope, 'life, 'p, 'd> FnOnce(
105 topology::Worker<'scope, 'life, 'p, 'd, S, I, C::Shutdown>,
106 ) -> R,
107 {
108 self.domain
109 .enter(context, (self.installer, op), report, finish)
110 }
111
112 pub fn run<'report, C, F>(
114 self,
115 context: C,
116 complete: &'report mut session::Completion,
117 report: impl recovery::Observe,
118 failed: impl for<'owner> FnOnce(
119 topology::RunError<
120 'owner,
121 convert::Infallible,
122 I::Error,
123 (I, ops::Run<'report>),
124 shutdown::Requested<C::Shutdown>,
125 C::Shutdown,
126 >,
127 ) -> Result<shutdown::Requested<C::Shutdown>, F>,
128 ) -> Result<shutdown::Requested<C::Shutdown>, F>
129 where
130 C: executor::Build,
131 I: recipe::Execute<S>,
132 {
133 self.enter(context, ops::Run(complete), report, |result| {
134 let error = match result {
135 Ok(Ok(done)) => return Ok(done),
136 Ok(Err(error)) => topology::RunError::Failure(error),
137 Err(error) => topology::RunError::from(error),
138 };
139 failed(error)
140 })
141 }
142}
143
144impl<S, I> Prepared<S, I>
145where
146 S: storage::Build,
147{
148 pub fn try_local<O, R, Done>(
149 self,
150 op: O,
151 report: impl recovery::Observe,
152 finish: impl for<'owner> FnOnce(
153 Result<R, topology::EnterError<'owner, S::Error, (I, O), R>>,
154 ) -> Done,
155 ) -> Done
156 where
157 O: for<'scope, 'life, 'p, 'd> ops::Operation<
158 'd,
159 topology::Worker<'scope, 'life, 'p, 'd, S, I, ()>,
160 Output = R,
161 >,
162 {
163 self.domain.try_local((self.installer, op), report, finish)
164 }
165
166 pub fn try_scoped<F, R, Done>(
167 self,
168 op: F,
169 report: impl recovery::Observe,
170 finish: impl for<'owner> FnOnce(
171 Result<R, topology::EnterError<'owner, S::Error, (I, F), R>>,
172 ) -> Done,
173 ) -> Done
174 where
175 F: for<'scope, 'life, 'p, 'd> FnOnce(
176 topology::Worker<'scope, 'life, 'p, 'd, S, I, ()>,
177 ) -> R,
178 {
179 self.domain.try_local((self.installer, op), report, finish)
180 }
181
182 pub fn try_enter<C, O, R, Done>(
183 self,
184 context: C,
185 op: O,
186 report: impl recovery::Observe,
187 finish: impl for<'owner> FnOnce(
188 Result<R, topology::EnterError<'owner, S::Error, (I, O), R, C::Shutdown>>,
189 ) -> Done,
190 ) -> Done
191 where
192 C: executor::Build,
193 O: for<'scope, 'life, 'p, 'd> ops::Operation<
194 'd,
195 topology::Worker<'scope, 'life, 'p, 'd, S, I, C::Shutdown>,
196 Output = R,
197 >,
198 {
199 self.domain
200 .try_enter(context, (self.installer, op), report, finish)
201 }
202
203 pub fn try_with<C, F, R, Done>(
204 self,
205 context: C,
206 op: F,
207 report: impl recovery::Observe,
208 finish: impl for<'owner> FnOnce(
209 Result<R, topology::EnterError<'owner, S::Error, (I, F), R, C::Shutdown>>,
210 ) -> Done,
211 ) -> Done
212 where
213 C: executor::Build,
214 F: for<'scope, 'life, 'p, 'd> FnOnce(
215 topology::Worker<'scope, 'life, 'p, 'd, S, I, C::Shutdown>,
216 ) -> R,
217 {
218 self.domain
219 .try_enter(context, (self.installer, op), report, finish)
220 }
221}
222
223impl<S, I> Prepared<S, I>
224where
225 S: storage::Create,
226{
227 pub fn try_create<F, R, Done>(
228 self,
229 op: F,
230 report: impl recovery::Observe,
231 finish: impl for<'owner> FnOnce(
232 Result<R, topology::EnterError<'owner, S::Error, (I, F), R>>,
233 ) -> Done,
234 ) -> Done
235 where
236 F: for<'scope, 'life, 'p, 'd> FnOnce(
237 topology::Worker<'scope, 'life, 'p, 'd, S, I, ()>,
238 ) -> R,
239 {
240 self.domain.try_create((self.installer, op), report, finish)
241 }
242
243 pub fn try_scope<O, R, Done>(
244 self,
245 op: O,
246 report: impl recovery::Observe,
247 finish: impl for<'owner> FnOnce(
248 Result<R, topology::EnterError<'owner, S::Error, (I, O), R>>,
249 ) -> Done,
250 ) -> Done
251 where
252 O: for<'scope, 'life, 'p, 'd> ops::Operation<
253 'd,
254 topology::Worker<'scope, 'life, 'p, 'd, S, I, ()>,
255 Output = R,
256 >,
257 {
258 self.domain.try_create((self.installer, op), report, finish)
259 }
260}