Right now, shutdown uses bespoke machinery and has awkward semantics: any live handles ([Session]Cursor, Session, GridFsUploadStream) that need server-side cleanup will either block shutdown or be dropped potentially without cleanup.
Handling async work that (a) can respond to a cancel request and (b) has async cleanup requirements has a standard solution in the Rust world now: use CancellationToken to watch for the request and TaskTracker to wait for the cleanup to finish.
Reworking shutdown to use these mechanisms will provide much more typical semantics: once shutdown is requested, the method will signal any open handles to execute cleanup and wait for that to finish. Attempting to use any of those handles post-shutdown will return an error.
Updating the handle types to allow a cancellation signal may be nontrivial, but IMO will also likely result in more understandable code (e.g. RUST-2013).