[SERVER-66261] Add a task executor that executes inline on the Future side Created: 05/May/22  Updated: 29/Oct/23  Resolved: 22/Mar/23

Status: Closed
Project: Core Server
Component/s: None
Affects Version/s: None
Fix Version/s: 7.0.0-rc0

Type: Task Priority: Major - P3
Reporter: Jack Mulrow Assignee: Amirsaman Memaripour
Resolution: Fixed Votes: 0
Labels: equality-ga
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Depends
is depended on by SERVER-72701 Create a synchronous transaction API ... Closed
Initiative
Problem/Incident
causes SERVER-82313 Fix cancelling txn api from the caller Closed
Related
related to SERVER-75291 Complete TODO listed in SERVER-66261 Open
related to SERVER-76363 Complete TODO listed in SERVER-66261 Backlog
related to SERVER-75166 Complete TODO listed in SERVER-66261 Closed
related to SERVER-76030 Complete TODO listed in SERVER-66261 Closed
Assigned Teams:
Service Arch
Backwards Compatibility: Fully Compatible
Sprint: Service Arch 2023-03-20, Service Arch 2023-04-03
Participants:
Linked BF Score: 105

 Description   

It would be nice to have an executor compatible with ExecutorFutures that executes its tasks inline on the caller's thread so we can run code written to be async compatible synchronously (like QueuedImmediateExecutor from facebook/folly). This would be especially useful for the recently added TransactionWithRetries type, which executes transaction commands on a given executor but every current use is in a synchronous context.

We already have the InlineQueuedCountingExecutor which seems to do this, but it's in a test file so is probably not production quality.


The initial use case for this will be `SyncTransactionWithRetries::runNoThrow`, which currently runs a work on an executor while using `get` to cause the main thread to wait. In this situation, there is no reason for the work to be run on a different thread.

This can be solved with a new type `ManuallyManagedExecutor`. 

Before:

Future fut = somethingThatTakesAnExecutor(_exec);
fut.get(); // Blocking call if fut is not ready. Work is done on a thread owned by `_exec`.

After:

ManuallyManagedExecutor exec();
Future fut = somethingThatTakesAnExecutor(exec);
exec.runUntilReady(fut); // Work is done on this thread.
fut.get(); // Not a blocking call because we know fut is ready.

Note: There are complications associated with the existing usage patterns around executors. Generally executors are managed with shared_ptr. This means that a function taking this sort of executor might hold onto it longer than the caller expected. The correct implementation will need to take this into account and have some concept of an owner, so when the owner goes out of scope, it can reject work or maybe forward work to a fallback executor (otherwise accidental users of this executor will just hang).



 Comments   
Comment by Githook User [ 23/Mar/23 ]

Author:

{'name': 'Amirsaman Memaripour', 'email': 'amirsaman.memaripour@mongodb.com', 'username': 'samanca'}

Message: SERVER-75166 Update TODOs referencing SERVER-66261
Branch: master
https://github.com/mongodb/mongo/commit/4afdeed8b36429b52fbf857bb94653ccc0c9489b

Comment by Githook User [ 22/Mar/23 ]

Author:

{'name': 'Amirsaman Memaripour', 'email': 'amirsaman.memaripour@mongodb.com', 'username': 'samanca'}

Message: SERVER-66261 Add an executor type that executes inline
Branch: master
https://github.com/mongodb/mongo/commit/611c01c5b68d1892513b54cd7c6e63b544345700

Generated at Thu Feb 08 06:04:55 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.