-
Type: Improvement
-
Resolution: Unresolved
-
Priority: Unknown
-
None
-
Affects Version/s: None
-
Component/s: Connection Layer, Sessions
note: needs writing ticket for the scope
As it stands today, NodeJS has no concept of scope-based resource management (RAII, defer blocks, with-as statements, destructors, ect in other languages) and consequently resources must be manually closed / cleaned up. This applies to async resources (i.e., closing a socket) but also synchronous resources (i.e., unsetting some internal state on a class after a function call is complete). There is a stage 3 ECMAScript proposal to add resource management helpers to the Javascript specification (proposal-explicit-resource-management), but it is only stage 3 and once it's fully accepted it will be at a minimum 3 years before resource management will be supported by the Node driver's minimum supported Node version.
Resource management issues are common in the Node driver
- Tests frequently time out in CI due to socket leaks or unconnected clients (resulting in the need for a custom socket leak / connected client meta test - https://github.com/mongodb/node-mongodb-native/blob/main/test/tools/runner/hooks/leak_checker.ts)
- Resource creation, usage and cleanup are often scattered across multiple methods, making it easy to forgot to cleanup the resource when the operation is completed. An example of forgetting to clean up a timeout can be found here - https://jira.mongodb.org/browse/NODE-4854.
try-finally is a currently supported construct that can be used to ensure cleanup code happens after any success or failure, but the architecture of the driver makes using try-finally blocks impractical for many use cases. For example, the timeout bug mentioned above is not preventable with a try-finally in the current architecture because the timeout is set in a synchronous function and cleared in a separate event listener - there is no codepath we can wrap inside the try finally.
We should consider design approaches that could improve our resource handling.
Resources
One approach would use an async middleware pattern to structure the driver in a manner where try-finally is practical to use. A rough POC that refactors operation execution into middleware is available here: https://github.com/baileympearson/node-mongodb-native/tree/middleware-poc.