Get the round trip test to pass.

The reason the test failed is that the future returned by `call` on the state
service was immediately dropped, rather than being driven to completion.
Instead, we link the state update future with the verification future by
.awaiting it in an async block.

Note that the state update future is constructed outside of the async block
returned by the verification service.  Why?  Because calling
`self.state_service.call` requires mutable access to `state_service`, which we
only have in the body of the verification service's `call` method, and not
during execution of the async block it returns (which could happen at some
later point, or never).

In Tower's model, the `call` method itself only does the work necessary to
construct a future that represents completion of the service call, and the rest
of the work is done in the future itself.  In particular, the fact that
`Service::call` takes `&mut self` means two things:

1. the service's state can be mutated while setting up the future, but not
during the future's subsequent execution,

2. any nested service calls made *by* the service *to* sub-services (e.g., the
verification service calling the state service) must either be made upfront,
while constructing the response future, or must be made to a clone of the
sub-service owned by the the response future.
This commit is contained in:
Henry de Valence 2020-06-11 10:45:04 -07:00
parent 15bc64aed9
commit adf0769ac2
1 changed files with 9 additions and 2 deletions

View File

@ -77,11 +77,18 @@ where
// - handle chain reorgs, adjust state_service "unique block height" conditions
// - handle block validation errors (including errors in the block's transactions)
// - handle state_service AddBlock errors, and add unit tests for those errors
let _: ZSF = self.state_service.call(zebra_state::Request::AddBlock {
// `state_service.call` is OK here because we already called
// `state_service.poll_ready` in our `poll_ready`.
let add_block = self.state_service.call(zebra_state::Request::AddBlock {
block: block.into(),
});
async move { Ok(header_hash) }.boxed()
async move {
add_block.await?;
Ok(header_hash)
}
.boxed()
}
}