Skip to content

Commit

Permalink
[update-engine] Tweaks to allow engine execution future to be Send (#…
Browse files Browse the repository at this point in the history
…2860)

While integrating update-engine and wicketd, I bumped into a couple
issues trying to `tokio::spawn()` a future involving an `UpdateEngine`
where the compiler didn't think the future was `Send` even though it
should have been; these changes taught the compiler what it needed to
know.
  • Loading branch information
jgallagher authored Apr 17, 2023
1 parent a378cda commit 4d442b4
Showing 1 changed file with 21 additions and 12 deletions.
33 changes: 21 additions & 12 deletions update-engine/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl<'a, S: StepSpec> UpdateEngine<'a, S> {
step_fn: F,
) -> NewStep<'_, 'a, S, T>
where
F: FnOnce(StepContext<S>) -> Fut + 'a,
F: FnOnce(StepContext<S>) -> Fut + Send + 'a,
Fut: Future<Output = Result<StepResult<T, S>, S::Error>> + Send + 'a,
T: Send + 'a,
{
Expand Down Expand Up @@ -254,7 +254,7 @@ impl<'engine, 'a, S: StepSpec> ComponentRegistrar<'engine, 'a, S> {
step_fn: F,
) -> NewStep<'engine, 'a, S, T>
where
F: FnOnce(StepContext<S>) -> Fut + 'a,
F: FnOnce(StepContext<S>) -> Fut + Send + 'a,
Fut: Future<Output = Result<StepResult<T, S>, S::Error>> + Send + 'a,
T: Send + 'a,
{
Expand Down Expand Up @@ -313,7 +313,7 @@ impl<'engine, 'a, S: StepSpec, T> NewStep<'engine, 'a, S, T> {
/// be infallible, and will often just be synchronous code.
pub fn with_metadata_fn<F, Fut>(mut self, f: F) -> Self
where
F: FnOnce(MetadataContext<S>) -> Fut + 'a,
F: FnOnce(MetadataContext<S>) -> Fut + Send + 'a,
Fut: Future<Output = S::StepMetadata> + Send + 'a,
{
self.metadata_fn = Some(DebugIgnore(Box::new(|cx| (f)(cx).boxed())));
Expand Down Expand Up @@ -518,6 +518,7 @@ type StepMetadataFn<'a, S> = Box<
dyn FnOnce(
MetadataContext<S>,
) -> BoxFuture<'a, <S as StepSpec>::StepMetadata>
+ Send
+ 'a,
>;

Expand All @@ -533,6 +534,7 @@ type StepExecFn<'a, S> = Box<
StepContext<S>,
)
-> BoxFuture<'a, Result<StepOutcome<S>, <S as StepSpec>::Error>>
+ Send
+ 'a,
>;

Expand Down Expand Up @@ -687,15 +689,22 @@ impl<S: StepSpec> StepProgressReporter<S> {
self,
error: &S::Error,
) -> Result<(), mpsc::error::SendError<Event<S>>> {
let error = error.as_error();
let message = error.to_string();

let mut current = error;
let mut causes = vec![];
while let Some(source) = current.source() {
causes.push(source.to_string());
current = source;
}
// Stringify `error` into a message + list causes; this is written the
// way it is to avoid `error` potentially living across the `.await`
// below (which can cause lifetime issues in callers).
let (message, causes) = {
let error = error.as_error();
let message = error.to_string();

let mut current = error;
let mut causes = vec![];
while let Some(source) = current.source() {
causes.push(source.to_string());
current = source;
}

(message, causes)
};

self.sender
.send(Event::Step(StepEvent {
Expand Down

0 comments on commit 4d442b4

Please sign in to comment.