|
The unit-tests for SessionWorkflow use a thread-pool to handle requests, implying that the command processing part runs on a separate thread than the one that initiates it:
Future<DbResponse> _handleRequest(OperationContext* opCtx, const Message& request) noexcept {
|
auto [p, f] = makePromiseFuture<DbResponse>();
|
ExecutorFuture<void>(_threadPool)
|
.then([this, opCtx, &request, p = std::move(p)]() mutable {
|
p.setWith([&] { return _processRequest(opCtx, request); });
|
})
|
.getAsync([](auto&&) {});
|
return std::move(f);
|
}
|
Since we are using ExecutorFuture here, the rest of the continuation shown below may run on a thread that doesn't have the Client attached:
...
|
auto fr = std::make_shared<Frame>(shared_from_this());
|
return _getNextWork()
|
.then([&, fr](auto work) {
|
fr->metrics.received();
|
invariant(!_work);
|
_work = std::move(work);
|
return _dispatchWork();
|
})
|
.then([&, fr](auto rsp) {
|
_acceptResponse(std::move(rsp));
|
fr->metrics.processed();
|
_sendResponse();
|
fr->metrics.sent(*session());
|
_yieldPointReached();
|
fr->metrics.yielded();
|
});
|
...
|
As part of running _acceptResponse, we detach and kill the opCtx that must happen on a thread than has the Client attached (through ClientStrand), but that may not be the case in unit-tests (for both dedicated and shared threading models).
|