@depup/mongodb 7.1.0-depup.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (396) hide show
  1. package/LICENSE.md +201 -0
  2. package/README.md +33 -0
  3. package/etc/prepare.js +12 -0
  4. package/lib/admin.js +136 -0
  5. package/lib/admin.js.map +1 -0
  6. package/lib/bson.js +85 -0
  7. package/lib/bson.js.map +1 -0
  8. package/lib/bulk/common.js +835 -0
  9. package/lib/bulk/common.js.map +1 -0
  10. package/lib/bulk/ordered.js +67 -0
  11. package/lib/bulk/ordered.js.map +1 -0
  12. package/lib/bulk/unordered.js +92 -0
  13. package/lib/bulk/unordered.js.map +1 -0
  14. package/lib/change_stream.js +513 -0
  15. package/lib/change_stream.js.map +1 -0
  16. package/lib/client-side-encryption/auto_encrypter.js +272 -0
  17. package/lib/client-side-encryption/auto_encrypter.js.map +1 -0
  18. package/lib/client-side-encryption/client_encryption.js +609 -0
  19. package/lib/client-side-encryption/client_encryption.js.map +1 -0
  20. package/lib/client-side-encryption/errors.js +138 -0
  21. package/lib/client-side-encryption/errors.js.map +1 -0
  22. package/lib/client-side-encryption/mongocryptd_manager.js +85 -0
  23. package/lib/client-side-encryption/mongocryptd_manager.js.map +1 -0
  24. package/lib/client-side-encryption/providers/aws.js +23 -0
  25. package/lib/client-side-encryption/providers/aws.js.map +1 -0
  26. package/lib/client-side-encryption/providers/azure.js +132 -0
  27. package/lib/client-side-encryption/providers/azure.js.map +1 -0
  28. package/lib/client-side-encryption/providers/gcp.js +16 -0
  29. package/lib/client-side-encryption/providers/gcp.js.map +1 -0
  30. package/lib/client-side-encryption/providers/index.js +43 -0
  31. package/lib/client-side-encryption/providers/index.js.map +1 -0
  32. package/lib/client-side-encryption/state_machine.js +427 -0
  33. package/lib/client-side-encryption/state_machine.js.map +1 -0
  34. package/lib/cmap/auth/auth_provider.js +51 -0
  35. package/lib/cmap/auth/auth_provider.js.map +1 -0
  36. package/lib/cmap/auth/aws4.js +161 -0
  37. package/lib/cmap/auth/aws4.js.map +1 -0
  38. package/lib/cmap/auth/aws_temporary_credentials.js +103 -0
  39. package/lib/cmap/auth/aws_temporary_credentials.js.map +1 -0
  40. package/lib/cmap/auth/gssapi.js +155 -0
  41. package/lib/cmap/auth/gssapi.js.map +1 -0
  42. package/lib/cmap/auth/mongo_credentials.js +169 -0
  43. package/lib/cmap/auth/mongo_credentials.js.map +1 -0
  44. package/lib/cmap/auth/mongodb_aws.js +128 -0
  45. package/lib/cmap/auth/mongodb_aws.js.map +1 -0
  46. package/lib/cmap/auth/mongodb_oidc/automated_callback_workflow.js +84 -0
  47. package/lib/cmap/auth/mongodb_oidc/automated_callback_workflow.js.map +1 -0
  48. package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js +62 -0
  49. package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js.map +1 -0
  50. package/lib/cmap/auth/mongodb_oidc/callback_workflow.js +141 -0
  51. package/lib/cmap/auth/mongodb_oidc/callback_workflow.js.map +1 -0
  52. package/lib/cmap/auth/mongodb_oidc/command_builders.js +44 -0
  53. package/lib/cmap/auth/mongodb_oidc/command_builders.js.map +1 -0
  54. package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js +39 -0
  55. package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js.map +1 -0
  56. package/lib/cmap/auth/mongodb_oidc/human_callback_workflow.js +122 -0
  57. package/lib/cmap/auth/mongodb_oidc/human_callback_workflow.js.map +1 -0
  58. package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js +32 -0
  59. package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js.map +1 -0
  60. package/lib/cmap/auth/mongodb_oidc/token_cache.js +52 -0
  61. package/lib/cmap/auth/mongodb_oidc/token_cache.js.map +1 -0
  62. package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js +23 -0
  63. package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js.map +1 -0
  64. package/lib/cmap/auth/mongodb_oidc.js +73 -0
  65. package/lib/cmap/auth/mongodb_oidc.js.map +1 -0
  66. package/lib/cmap/auth/plain.js +26 -0
  67. package/lib/cmap/auth/plain.js.map +1 -0
  68. package/lib/cmap/auth/providers.js +22 -0
  69. package/lib/cmap/auth/providers.js.map +1 -0
  70. package/lib/cmap/auth/scram.js +254 -0
  71. package/lib/cmap/auth/scram.js.map +1 -0
  72. package/lib/cmap/auth/x509.js +36 -0
  73. package/lib/cmap/auth/x509.js.map +1 -0
  74. package/lib/cmap/command_monitoring_events.js +223 -0
  75. package/lib/cmap/command_monitoring_events.js.map +1 -0
  76. package/lib/cmap/commands.js +535 -0
  77. package/lib/cmap/commands.js.map +1 -0
  78. package/lib/cmap/connect.js +381 -0
  79. package/lib/cmap/connect.js.map +1 -0
  80. package/lib/cmap/connection.js +571 -0
  81. package/lib/cmap/connection.js.map +1 -0
  82. package/lib/cmap/connection_pool.js +558 -0
  83. package/lib/cmap/connection_pool.js.map +1 -0
  84. package/lib/cmap/connection_pool_events.js +190 -0
  85. package/lib/cmap/connection_pool_events.js.map +1 -0
  86. package/lib/cmap/errors.js +108 -0
  87. package/lib/cmap/errors.js.map +1 -0
  88. package/lib/cmap/handshake/client_metadata.js +242 -0
  89. package/lib/cmap/handshake/client_metadata.js.map +1 -0
  90. package/lib/cmap/metrics.js +62 -0
  91. package/lib/cmap/metrics.js.map +1 -0
  92. package/lib/cmap/stream_description.js +70 -0
  93. package/lib/cmap/stream_description.js.map +1 -0
  94. package/lib/cmap/wire_protocol/compression.js +178 -0
  95. package/lib/cmap/wire_protocol/compression.js.map +1 -0
  96. package/lib/cmap/wire_protocol/constants.js +21 -0
  97. package/lib/cmap/wire_protocol/constants.js.map +1 -0
  98. package/lib/cmap/wire_protocol/on_data.js +111 -0
  99. package/lib/cmap/wire_protocol/on_data.js.map +1 -0
  100. package/lib/cmap/wire_protocol/on_demand/document.js +222 -0
  101. package/lib/cmap/wire_protocol/on_demand/document.js.map +1 -0
  102. package/lib/cmap/wire_protocol/responses.js +315 -0
  103. package/lib/cmap/wire_protocol/responses.js.map +1 -0
  104. package/lib/cmap/wire_protocol/shared.js +35 -0
  105. package/lib/cmap/wire_protocol/shared.js.map +1 -0
  106. package/lib/collection.js +751 -0
  107. package/lib/collection.js.map +1 -0
  108. package/lib/connection_string.js +1090 -0
  109. package/lib/connection_string.js.map +1 -0
  110. package/lib/constants.js +170 -0
  111. package/lib/constants.js.map +1 -0
  112. package/lib/cursor/abstract_cursor.js +924 -0
  113. package/lib/cursor/abstract_cursor.js.map +1 -0
  114. package/lib/cursor/aggregation_cursor.js +164 -0
  115. package/lib/cursor/aggregation_cursor.js.map +1 -0
  116. package/lib/cursor/change_stream_cursor.js +104 -0
  117. package/lib/cursor/change_stream_cursor.js.map +1 -0
  118. package/lib/cursor/client_bulk_write_cursor.js +52 -0
  119. package/lib/cursor/client_bulk_write_cursor.js.map +1 -0
  120. package/lib/cursor/explainable_cursor.js +36 -0
  121. package/lib/cursor/explainable_cursor.js.map +1 -0
  122. package/lib/cursor/find_cursor.js +399 -0
  123. package/lib/cursor/find_cursor.js.map +1 -0
  124. package/lib/cursor/list_collections_cursor.js +34 -0
  125. package/lib/cursor/list_collections_cursor.js.map +1 -0
  126. package/lib/cursor/list_indexes_cursor.js +32 -0
  127. package/lib/cursor/list_indexes_cursor.js.map +1 -0
  128. package/lib/cursor/list_search_indexes_cursor.js +14 -0
  129. package/lib/cursor/list_search_indexes_cursor.js.map +1 -0
  130. package/lib/cursor/run_command_cursor.js +94 -0
  131. package/lib/cursor/run_command_cursor.js.map +1 -0
  132. package/lib/db.js +419 -0
  133. package/lib/db.js.map +1 -0
  134. package/lib/deps.js +112 -0
  135. package/lib/deps.js.map +1 -0
  136. package/lib/encrypter.js +106 -0
  137. package/lib/encrypter.js.map +1 -0
  138. package/lib/error.js +1380 -0
  139. package/lib/error.js.map +1 -0
  140. package/lib/explain.js +59 -0
  141. package/lib/explain.js.map +1 -0
  142. package/lib/gridfs/download.js +305 -0
  143. package/lib/gridfs/download.js.map +1 -0
  144. package/lib/gridfs/index.js +164 -0
  145. package/lib/gridfs/index.js.map +1 -0
  146. package/lib/gridfs/upload.js +358 -0
  147. package/lib/gridfs/upload.js.map +1 -0
  148. package/lib/index.js +193 -0
  149. package/lib/index.js.map +1 -0
  150. package/lib/mongo_client.js +557 -0
  151. package/lib/mongo_client.js.map +1 -0
  152. package/lib/mongo_client_auth_providers.js +80 -0
  153. package/lib/mongo_client_auth_providers.js.map +1 -0
  154. package/lib/mongo_logger.js +655 -0
  155. package/lib/mongo_logger.js.map +1 -0
  156. package/lib/mongo_types.js +56 -0
  157. package/lib/mongo_types.js.map +1 -0
  158. package/lib/operations/aggregate.js +90 -0
  159. package/lib/operations/aggregate.js.map +1 -0
  160. package/lib/operations/client_bulk_write/client_bulk_write.js +51 -0
  161. package/lib/operations/client_bulk_write/client_bulk_write.js.map +1 -0
  162. package/lib/operations/client_bulk_write/command_builder.js +340 -0
  163. package/lib/operations/client_bulk_write/command_builder.js.map +1 -0
  164. package/lib/operations/client_bulk_write/common.js +3 -0
  165. package/lib/operations/client_bulk_write/common.js.map +1 -0
  166. package/lib/operations/client_bulk_write/executor.js +120 -0
  167. package/lib/operations/client_bulk_write/executor.js.map +1 -0
  168. package/lib/operations/client_bulk_write/results_merger.js +204 -0
  169. package/lib/operations/client_bulk_write/results_merger.js.map +1 -0
  170. package/lib/operations/command.js +83 -0
  171. package/lib/operations/command.js.map +1 -0
  172. package/lib/operations/count.js +45 -0
  173. package/lib/operations/count.js.map +1 -0
  174. package/lib/operations/create_collection.js +109 -0
  175. package/lib/operations/create_collection.js.map +1 -0
  176. package/lib/operations/delete.js +125 -0
  177. package/lib/operations/delete.js.map +1 -0
  178. package/lib/operations/distinct.js +61 -0
  179. package/lib/operations/distinct.js.map +1 -0
  180. package/lib/operations/drop.js +93 -0
  181. package/lib/operations/drop.js.map +1 -0
  182. package/lib/operations/end_sessions.js +34 -0
  183. package/lib/operations/end_sessions.js.map +1 -0
  184. package/lib/operations/estimated_document_count.js +41 -0
  185. package/lib/operations/estimated_document_count.js.map +1 -0
  186. package/lib/operations/execute_operation.js +239 -0
  187. package/lib/operations/execute_operation.js.map +1 -0
  188. package/lib/operations/find.js +148 -0
  189. package/lib/operations/find.js.map +1 -0
  190. package/lib/operations/find_and_modify.js +158 -0
  191. package/lib/operations/find_and_modify.js.map +1 -0
  192. package/lib/operations/get_more.js +62 -0
  193. package/lib/operations/get_more.js.map +1 -0
  194. package/lib/operations/indexes.js +186 -0
  195. package/lib/operations/indexes.js.map +1 -0
  196. package/lib/operations/insert.js +70 -0
  197. package/lib/operations/insert.js.map +1 -0
  198. package/lib/operations/kill_cursors.js +43 -0
  199. package/lib/operations/kill_cursors.js.map +1 -0
  200. package/lib/operations/list_collections.js +53 -0
  201. package/lib/operations/list_collections.js.map +1 -0
  202. package/lib/operations/list_databases.js +40 -0
  203. package/lib/operations/list_databases.js.map +1 -0
  204. package/lib/operations/operation.js +102 -0
  205. package/lib/operations/operation.js.map +1 -0
  206. package/lib/operations/profiling_level.js +43 -0
  207. package/lib/operations/profiling_level.js.map +1 -0
  208. package/lib/operations/remove_user.js +27 -0
  209. package/lib/operations/remove_user.js.map +1 -0
  210. package/lib/operations/rename.js +38 -0
  211. package/lib/operations/rename.js.map +1 -0
  212. package/lib/operations/run_command.js +47 -0
  213. package/lib/operations/run_command.js.map +1 -0
  214. package/lib/operations/search_indexes/create.js +33 -0
  215. package/lib/operations/search_indexes/create.js.map +1 -0
  216. package/lib/operations/search_indexes/drop.js +43 -0
  217. package/lib/operations/search_indexes/drop.js.map +1 -0
  218. package/lib/operations/search_indexes/update.js +35 -0
  219. package/lib/operations/search_indexes/update.js.map +1 -0
  220. package/lib/operations/set_profiling_level.js +53 -0
  221. package/lib/operations/set_profiling_level.js.map +1 -0
  222. package/lib/operations/stats.js +27 -0
  223. package/lib/operations/stats.js.map +1 -0
  224. package/lib/operations/update.js +188 -0
  225. package/lib/operations/update.js.map +1 -0
  226. package/lib/operations/validate_collection.js +37 -0
  227. package/lib/operations/validate_collection.js.map +1 -0
  228. package/lib/read_concern.js +73 -0
  229. package/lib/read_concern.js.map +1 -0
  230. package/lib/read_preference.js +191 -0
  231. package/lib/read_preference.js.map +1 -0
  232. package/lib/sdam/common.js +49 -0
  233. package/lib/sdam/common.js.map +1 -0
  234. package/lib/sdam/events.js +146 -0
  235. package/lib/sdam/events.js.map +1 -0
  236. package/lib/sdam/monitor.js +544 -0
  237. package/lib/sdam/monitor.js.map +1 -0
  238. package/lib/sdam/server.js +404 -0
  239. package/lib/sdam/server.js.map +1 -0
  240. package/lib/sdam/server_description.js +204 -0
  241. package/lib/sdam/server_description.js.map +1 -0
  242. package/lib/sdam/server_selection.js +294 -0
  243. package/lib/sdam/server_selection.js.map +1 -0
  244. package/lib/sdam/server_selection_events.js +85 -0
  245. package/lib/sdam/server_selection_events.js.map +1 -0
  246. package/lib/sdam/srv_polling.js +108 -0
  247. package/lib/sdam/srv_polling.js.map +1 -0
  248. package/lib/sdam/topology.js +652 -0
  249. package/lib/sdam/topology.js.map +1 -0
  250. package/lib/sdam/topology_description.js +383 -0
  251. package/lib/sdam/topology_description.js.map +1 -0
  252. package/lib/sessions.js +892 -0
  253. package/lib/sessions.js.map +1 -0
  254. package/lib/sort.js +103 -0
  255. package/lib/sort.js.map +1 -0
  256. package/lib/timeout.js +296 -0
  257. package/lib/timeout.js.map +1 -0
  258. package/lib/transactions.js +135 -0
  259. package/lib/transactions.js.map +1 -0
  260. package/lib/utils.js +1163 -0
  261. package/lib/utils.js.map +1 -0
  262. package/lib/write_concern.js +100 -0
  263. package/lib/write_concern.js.map +1 -0
  264. package/mongodb.d.ts +9018 -0
  265. package/package.json +197 -0
  266. package/src/admin.ts +173 -0
  267. package/src/bson.ts +149 -0
  268. package/src/bulk/common.ts +1251 -0
  269. package/src/bulk/ordered.ts +83 -0
  270. package/src/bulk/unordered.ts +115 -0
  271. package/src/change_stream.ts +1160 -0
  272. package/src/client-side-encryption/auto_encrypter.ts +469 -0
  273. package/src/client-side-encryption/client_encryption.ts +1150 -0
  274. package/src/client-side-encryption/errors.ts +144 -0
  275. package/src/client-side-encryption/mongocryptd_manager.ts +100 -0
  276. package/src/client-side-encryption/providers/aws.ts +33 -0
  277. package/src/client-side-encryption/providers/azure.ts +181 -0
  278. package/src/client-side-encryption/providers/gcp.ts +16 -0
  279. package/src/client-side-encryption/providers/index.ts +207 -0
  280. package/src/client-side-encryption/state_machine.ts +651 -0
  281. package/src/cmap/auth/auth_provider.ts +77 -0
  282. package/src/cmap/auth/aws4.ts +207 -0
  283. package/src/cmap/auth/aws_temporary_credentials.ts +129 -0
  284. package/src/cmap/auth/gssapi.ts +203 -0
  285. package/src/cmap/auth/mongo_credentials.ts +292 -0
  286. package/src/cmap/auth/mongodb_aws.ts +179 -0
  287. package/src/cmap/auth/mongodb_oidc/automated_callback_workflow.ts +88 -0
  288. package/src/cmap/auth/mongodb_oidc/azure_machine_workflow.ts +73 -0
  289. package/src/cmap/auth/mongodb_oidc/callback_workflow.ts +188 -0
  290. package/src/cmap/auth/mongodb_oidc/command_builders.ts +53 -0
  291. package/src/cmap/auth/mongodb_oidc/gcp_machine_workflow.ts +46 -0
  292. package/src/cmap/auth/mongodb_oidc/human_callback_workflow.ts +141 -0
  293. package/src/cmap/auth/mongodb_oidc/k8s_machine_workflow.ts +31 -0
  294. package/src/cmap/auth/mongodb_oidc/token_cache.ts +62 -0
  295. package/src/cmap/auth/mongodb_oidc/token_machine_workflow.ts +22 -0
  296. package/src/cmap/auth/mongodb_oidc.ts +185 -0
  297. package/src/cmap/auth/plain.ts +25 -0
  298. package/src/cmap/auth/providers.ts +22 -0
  299. package/src/cmap/auth/scram.ts +344 -0
  300. package/src/cmap/auth/x509.ts +43 -0
  301. package/src/cmap/command_monitoring_events.ts +316 -0
  302. package/src/cmap/commands.ts +788 -0
  303. package/src/cmap/connect.ts +518 -0
  304. package/src/cmap/connection.ts +931 -0
  305. package/src/cmap/connection_pool.ts +831 -0
  306. package/src/cmap/connection_pool_events.ts +300 -0
  307. package/src/cmap/errors.ts +119 -0
  308. package/src/cmap/handshake/client_metadata.ts +353 -0
  309. package/src/cmap/metrics.ts +58 -0
  310. package/src/cmap/stream_description.ts +96 -0
  311. package/src/cmap/wire_protocol/compression.ts +211 -0
  312. package/src/cmap/wire_protocol/constants.ts +17 -0
  313. package/src/cmap/wire_protocol/on_data.ts +139 -0
  314. package/src/cmap/wire_protocol/on_demand/document.ts +358 -0
  315. package/src/cmap/wire_protocol/responses.ts +393 -0
  316. package/src/cmap/wire_protocol/shared.ts +48 -0
  317. package/src/collection.ts +1314 -0
  318. package/src/connection_string.ts +1297 -0
  319. package/src/constants.ts +176 -0
  320. package/src/cursor/abstract_cursor.ts +1247 -0
  321. package/src/cursor/aggregation_cursor.ts +245 -0
  322. package/src/cursor/change_stream_cursor.ts +171 -0
  323. package/src/cursor/client_bulk_write_cursor.ts +83 -0
  324. package/src/cursor/explainable_cursor.ts +51 -0
  325. package/src/cursor/find_cursor.ts +497 -0
  326. package/src/cursor/list_collections_cursor.ts +50 -0
  327. package/src/cursor/list_indexes_cursor.ts +37 -0
  328. package/src/cursor/list_search_indexes_cursor.ts +20 -0
  329. package/src/cursor/run_command_cursor.ts +178 -0
  330. package/src/db.ts +621 -0
  331. package/src/deps.ts +227 -0
  332. package/src/encrypter.ts +127 -0
  333. package/src/error.ts +1567 -0
  334. package/src/explain.ts +124 -0
  335. package/src/gridfs/download.ts +483 -0
  336. package/src/gridfs/index.ts +264 -0
  337. package/src/gridfs/upload.ts +537 -0
  338. package/src/index.ts +633 -0
  339. package/src/mongo_client.ts +1155 -0
  340. package/src/mongo_client_auth_providers.ts +87 -0
  341. package/src/mongo_logger.ts +1081 -0
  342. package/src/mongo_types.ts +678 -0
  343. package/src/operations/aggregate.ts +153 -0
  344. package/src/operations/client_bulk_write/client_bulk_write.ts +72 -0
  345. package/src/operations/client_bulk_write/command_builder.ts +487 -0
  346. package/src/operations/client_bulk_write/common.ts +276 -0
  347. package/src/operations/client_bulk_write/executor.ts +149 -0
  348. package/src/operations/client_bulk_write/results_merger.ts +260 -0
  349. package/src/operations/command.ts +171 -0
  350. package/src/operations/count.ts +74 -0
  351. package/src/operations/create_collection.ts +218 -0
  352. package/src/operations/delete.ts +183 -0
  353. package/src/operations/distinct.ts +92 -0
  354. package/src/operations/drop.ts +130 -0
  355. package/src/operations/end_sessions.ts +44 -0
  356. package/src/operations/estimated_document_count.ts +61 -0
  357. package/src/operations/execute_operation.ts +319 -0
  358. package/src/operations/find.ts +254 -0
  359. package/src/operations/find_and_modify.ts +319 -0
  360. package/src/operations/get_more.ts +108 -0
  361. package/src/operations/indexes.ts +418 -0
  362. package/src/operations/insert.ts +108 -0
  363. package/src/operations/kill_cursors.ts +64 -0
  364. package/src/operations/list_collections.ts +108 -0
  365. package/src/operations/list_databases.ts +68 -0
  366. package/src/operations/operation.ts +181 -0
  367. package/src/operations/profiling_level.ts +46 -0
  368. package/src/operations/remove_user.ts +36 -0
  369. package/src/operations/rename.ts +60 -0
  370. package/src/operations/run_command.ts +79 -0
  371. package/src/operations/search_indexes/create.ts +56 -0
  372. package/src/operations/search_indexes/drop.ts +58 -0
  373. package/src/operations/search_indexes/update.ts +45 -0
  374. package/src/operations/set_profiling_level.ts +74 -0
  375. package/src/operations/stats.ts +37 -0
  376. package/src/operations/update.ts +318 -0
  377. package/src/operations/validate_collection.ts +50 -0
  378. package/src/read_concern.ts +88 -0
  379. package/src/read_preference.ts +256 -0
  380. package/src/sdam/common.ts +74 -0
  381. package/src/sdam/events.ts +219 -0
  382. package/src/sdam/monitor.ts +771 -0
  383. package/src/sdam/server.ts +595 -0
  384. package/src/sdam/server_description.ts +297 -0
  385. package/src/sdam/server_selection.ts +415 -0
  386. package/src/sdam/server_selection_events.ts +142 -0
  387. package/src/sdam/srv_polling.ts +146 -0
  388. package/src/sdam/topology.ts +1100 -0
  389. package/src/sdam/topology_description.ts +548 -0
  390. package/src/sessions.ts +1244 -0
  391. package/src/sort.ts +141 -0
  392. package/src/timeout.ts +405 -0
  393. package/src/transactions.ts +181 -0
  394. package/src/utils.ts +1434 -0
  395. package/src/write_concern.ts +183 -0
  396. package/tsconfig.json +46 -0
@@ -0,0 +1,771 @@
1
+ import { clearTimeout, setTimeout } from 'timers';
2
+
3
+ import { type Document, Long } from '../bson';
4
+ import { connect, makeConnection, makeSocket, performInitialHandshake } from '../cmap/connect';
5
+ import type { Connection, ConnectionOptions } from '../cmap/connection';
6
+ import { getFAASEnv } from '../cmap/handshake/client_metadata';
7
+ import { LEGACY_HELLO_COMMAND } from '../constants';
8
+ import { MongoError, MongoErrorLabel, MongoNetworkTimeoutError } from '../error';
9
+ import { MongoLoggableComponent } from '../mongo_logger';
10
+ import { CancellationToken, TypedEventEmitter } from '../mongo_types';
11
+ import {
12
+ calculateDurationInMs,
13
+ type Callback,
14
+ type EventEmitterWithState,
15
+ makeStateMachine,
16
+ noop,
17
+ ns,
18
+ processTimeMS
19
+ } from '../utils';
20
+ import { ServerType, STATE_CLOSED, STATE_CLOSING } from './common';
21
+ import {
22
+ ServerHeartbeatFailedEvent,
23
+ ServerHeartbeatStartedEvent,
24
+ ServerHeartbeatSucceededEvent
25
+ } from './events';
26
+ import { Server } from './server';
27
+ import type { TopologyVersion } from './server_description';
28
+
29
+ const STATE_IDLE = 'idle';
30
+ const STATE_MONITORING = 'monitoring';
31
+ const stateTransition = makeStateMachine({
32
+ [STATE_CLOSING]: [STATE_CLOSING, STATE_IDLE, STATE_CLOSED],
33
+ [STATE_CLOSED]: [STATE_CLOSED, STATE_MONITORING],
34
+ [STATE_IDLE]: [STATE_IDLE, STATE_MONITORING, STATE_CLOSING],
35
+ [STATE_MONITORING]: [STATE_MONITORING, STATE_IDLE, STATE_CLOSING]
36
+ });
37
+
38
+ const INVALID_REQUEST_CHECK_STATES = new Set([STATE_CLOSING, STATE_CLOSED, STATE_MONITORING]);
39
+ function isInCloseState(monitor: Monitor) {
40
+ return monitor.s.state === STATE_CLOSED || monitor.s.state === STATE_CLOSING;
41
+ }
42
+
43
+ /** @public */
44
+ export const ServerMonitoringMode = Object.freeze({
45
+ auto: 'auto',
46
+ poll: 'poll',
47
+ stream: 'stream'
48
+ } as const);
49
+
50
+ /** @public */
51
+ export type ServerMonitoringMode = (typeof ServerMonitoringMode)[keyof typeof ServerMonitoringMode];
52
+
53
+ /** @internal */
54
+ export interface MonitorPrivate {
55
+ state: string;
56
+ }
57
+
58
+ /** @public */
59
+ export interface MonitorOptions
60
+ extends Omit<ConnectionOptions, 'id' | 'generation' | 'hostAddress'> {
61
+ connectTimeoutMS: number;
62
+ heartbeatFrequencyMS: number;
63
+ minHeartbeatFrequencyMS: number;
64
+ serverMonitoringMode: ServerMonitoringMode;
65
+ }
66
+
67
+ /** @public */
68
+ export type MonitorEvents = {
69
+ serverHeartbeatStarted(event: ServerHeartbeatStartedEvent): void;
70
+ serverHeartbeatSucceeded(event: ServerHeartbeatSucceededEvent): void;
71
+ serverHeartbeatFailed(event: ServerHeartbeatFailedEvent): void;
72
+ resetServer(error?: MongoError): void;
73
+ resetConnectionPool(): void;
74
+ close(): void;
75
+ } & EventEmitterWithState;
76
+
77
+ /** @internal */
78
+ export class Monitor extends TypedEventEmitter<MonitorEvents> {
79
+ /** @internal */
80
+ s: MonitorPrivate;
81
+ address: string;
82
+ options: Readonly<
83
+ Pick<
84
+ MonitorOptions,
85
+ | 'connectTimeoutMS'
86
+ | 'heartbeatFrequencyMS'
87
+ | 'minHeartbeatFrequencyMS'
88
+ | 'serverMonitoringMode'
89
+ >
90
+ >;
91
+ connectOptions: ConnectionOptions;
92
+ isRunningInFaasEnv: boolean;
93
+ server: Server;
94
+ connection: Connection | null;
95
+ cancellationToken: CancellationToken;
96
+ /** @internal */
97
+ monitorId?: MonitorInterval;
98
+ rttPinger?: RTTPinger;
99
+ /** @internal */
100
+ override component = MongoLoggableComponent.TOPOLOGY;
101
+ /** @internal */
102
+ private rttSampler: RTTSampler;
103
+
104
+ constructor(server: Server, options: MonitorOptions) {
105
+ super();
106
+ this.on('error', noop);
107
+
108
+ this.server = server;
109
+ this.connection = null;
110
+ this.cancellationToken = new CancellationToken();
111
+ this.cancellationToken.setMaxListeners(Infinity);
112
+ this.monitorId = undefined;
113
+ this.s = {
114
+ state: STATE_CLOSED
115
+ };
116
+ this.address = server.description.address;
117
+ this.options = Object.freeze({
118
+ connectTimeoutMS: options.connectTimeoutMS ?? 10000,
119
+ heartbeatFrequencyMS: options.heartbeatFrequencyMS ?? 10000,
120
+ minHeartbeatFrequencyMS: options.minHeartbeatFrequencyMS ?? 500,
121
+ serverMonitoringMode: options.serverMonitoringMode
122
+ });
123
+ this.isRunningInFaasEnv = getFAASEnv() != null;
124
+ this.mongoLogger = this.server.topology.client?.mongoLogger;
125
+ this.rttSampler = new RTTSampler(10);
126
+
127
+ const cancellationToken = this.cancellationToken;
128
+ // TODO: refactor this to pull it directly from the pool, requires new ConnectionPool integration
129
+ const connectOptions = {
130
+ id: '<monitor>' as const,
131
+ generation: server.pool.generation,
132
+ cancellationToken,
133
+ hostAddress: server.description.hostAddress,
134
+ ...options,
135
+ // force BSON serialization options
136
+ raw: false,
137
+ useBigInt64: false,
138
+ promoteLongs: true,
139
+ promoteValues: true,
140
+ promoteBuffers: true
141
+ };
142
+
143
+ // ensure no authentication is used for monitoring
144
+ delete connectOptions.credentials;
145
+ if (connectOptions.autoEncrypter) {
146
+ delete connectOptions.autoEncrypter;
147
+ }
148
+
149
+ this.connectOptions = Object.freeze(connectOptions);
150
+ }
151
+
152
+ connect(): void {
153
+ if (this.s.state !== STATE_CLOSED) {
154
+ return;
155
+ }
156
+
157
+ // start
158
+ const heartbeatFrequencyMS = this.options.heartbeatFrequencyMS;
159
+ const minHeartbeatFrequencyMS = this.options.minHeartbeatFrequencyMS;
160
+ this.monitorId = new MonitorInterval(monitorServer(this), {
161
+ heartbeatFrequencyMS: heartbeatFrequencyMS,
162
+ minHeartbeatFrequencyMS: minHeartbeatFrequencyMS,
163
+ immediate: true
164
+ });
165
+ }
166
+
167
+ requestCheck(): void {
168
+ if (INVALID_REQUEST_CHECK_STATES.has(this.s.state)) {
169
+ return;
170
+ }
171
+
172
+ this.monitorId?.wake();
173
+ }
174
+
175
+ reset(): void {
176
+ const topologyVersion = this.server.description.topologyVersion;
177
+ if (isInCloseState(this) || topologyVersion == null) {
178
+ return;
179
+ }
180
+
181
+ stateTransition(this, STATE_CLOSING);
182
+ resetMonitorState(this);
183
+
184
+ // restart monitor
185
+ stateTransition(this, STATE_IDLE);
186
+
187
+ // restart monitoring
188
+ const heartbeatFrequencyMS = this.options.heartbeatFrequencyMS;
189
+ const minHeartbeatFrequencyMS = this.options.minHeartbeatFrequencyMS;
190
+ this.monitorId = new MonitorInterval(monitorServer(this), {
191
+ heartbeatFrequencyMS: heartbeatFrequencyMS,
192
+ minHeartbeatFrequencyMS: minHeartbeatFrequencyMS
193
+ });
194
+ }
195
+
196
+ close(): void {
197
+ if (isInCloseState(this)) {
198
+ return;
199
+ }
200
+
201
+ stateTransition(this, STATE_CLOSING);
202
+ resetMonitorState(this);
203
+
204
+ // close monitor
205
+ this.emit('close');
206
+ stateTransition(this, STATE_CLOSED);
207
+ }
208
+
209
+ get roundTripTime(): number {
210
+ return this.rttSampler.average();
211
+ }
212
+
213
+ get minRoundTripTime(): number {
214
+ return this.rttSampler.min();
215
+ }
216
+
217
+ get latestRtt(): number | null {
218
+ return this.rttSampler.last;
219
+ }
220
+
221
+ addRttSample(rtt: number) {
222
+ this.rttSampler.addSample(rtt);
223
+ }
224
+
225
+ clearRttSamples() {
226
+ this.rttSampler.clear();
227
+ }
228
+ }
229
+
230
+ function resetMonitorState(monitor: Monitor) {
231
+ monitor.monitorId?.stop();
232
+ monitor.monitorId = undefined;
233
+
234
+ monitor.rttPinger?.close();
235
+ monitor.rttPinger = undefined;
236
+
237
+ monitor.cancellationToken.emit('cancel');
238
+
239
+ monitor.connection?.destroy();
240
+ monitor.connection = null;
241
+
242
+ monitor.clearRttSamples();
243
+ }
244
+
245
+ function useStreamingProtocol(monitor: Monitor, topologyVersion: TopologyVersion | null): boolean {
246
+ // If we have no topology version we always poll no matter
247
+ // what the user provided, since the server does not support
248
+ // the streaming protocol.
249
+ if (topologyVersion == null) return false;
250
+
251
+ const serverMonitoringMode = monitor.options.serverMonitoringMode;
252
+ if (serverMonitoringMode === ServerMonitoringMode.poll) return false;
253
+ if (serverMonitoringMode === ServerMonitoringMode.stream) return true;
254
+
255
+ // If we are in auto mode, we need to figure out if we're in a FaaS
256
+ // environment or not and choose the appropriate mode.
257
+ if (monitor.isRunningInFaasEnv) return false;
258
+ return true;
259
+ }
260
+
261
+ function checkServer(monitor: Monitor, callback: Callback<Document | null>) {
262
+ let start: number;
263
+ let awaited: boolean;
264
+ const topologyVersion = monitor.server.description.topologyVersion;
265
+ const isAwaitable = useStreamingProtocol(monitor, topologyVersion);
266
+ monitor.emitAndLogHeartbeat(
267
+ Server.SERVER_HEARTBEAT_STARTED,
268
+ monitor.server.topology.s.id,
269
+ undefined,
270
+ new ServerHeartbeatStartedEvent(monitor.address, isAwaitable)
271
+ );
272
+
273
+ function onHeartbeatFailed(err: Error) {
274
+ monitor.connection?.destroy();
275
+ monitor.connection = null;
276
+ monitor.emitAndLogHeartbeat(
277
+ Server.SERVER_HEARTBEAT_FAILED,
278
+ monitor.server.topology.s.id,
279
+ undefined,
280
+ new ServerHeartbeatFailedEvent(monitor.address, calculateDurationInMs(start), err, awaited)
281
+ );
282
+
283
+ const error = !(err instanceof MongoError)
284
+ ? new MongoError(MongoError.buildErrorMessage(err), { cause: err })
285
+ : err;
286
+ error.addErrorLabel(MongoErrorLabel.ResetPool);
287
+ if (error instanceof MongoNetworkTimeoutError) {
288
+ error.addErrorLabel(MongoErrorLabel.InterruptInUseConnections);
289
+ }
290
+
291
+ monitor.emit('resetServer', error);
292
+ callback(err);
293
+ }
294
+
295
+ function onHeartbeatSucceeded(hello: Document) {
296
+ if (!('isWritablePrimary' in hello)) {
297
+ // Provide hello-style response document.
298
+ hello.isWritablePrimary = hello[LEGACY_HELLO_COMMAND];
299
+ }
300
+
301
+ // NOTE: here we use the latestRtt as this measurement corresponds with the value
302
+ // obtained for this successful heartbeat, if there is no latestRtt, then we calculate the
303
+ // duration
304
+ const duration =
305
+ isAwaitable && monitor.rttPinger
306
+ ? (monitor.rttPinger.latestRtt ?? calculateDurationInMs(start))
307
+ : calculateDurationInMs(start);
308
+
309
+ monitor.addRttSample(duration);
310
+
311
+ monitor.emitAndLogHeartbeat(
312
+ Server.SERVER_HEARTBEAT_SUCCEEDED,
313
+ monitor.server.topology.s.id,
314
+ hello.connectionId,
315
+ new ServerHeartbeatSucceededEvent(monitor.address, duration, hello, isAwaitable)
316
+ );
317
+
318
+ if (isAwaitable) {
319
+ // If we are using the streaming protocol then we immediately issue another 'started'
320
+ // event, otherwise the "check" is complete and return to the main monitor loop
321
+ monitor.emitAndLogHeartbeat(
322
+ Server.SERVER_HEARTBEAT_STARTED,
323
+ monitor.server.topology.s.id,
324
+ undefined,
325
+ new ServerHeartbeatStartedEvent(monitor.address, true)
326
+ );
327
+ // We have not actually sent an outgoing handshake, but when we get the next response we
328
+ // want the duration to reflect the time since we last heard from the server
329
+ start = processTimeMS();
330
+ } else {
331
+ monitor.rttPinger?.close();
332
+ monitor.rttPinger = undefined;
333
+
334
+ callback(undefined, hello);
335
+ }
336
+ }
337
+
338
+ const { connection } = monitor;
339
+ if (connection && !connection.closed) {
340
+ const { serverApi, helloOk } = connection;
341
+ const connectTimeoutMS = monitor.options.connectTimeoutMS;
342
+ const maxAwaitTimeMS = monitor.options.heartbeatFrequencyMS;
343
+
344
+ const cmd = {
345
+ [serverApi?.version || helloOk ? 'hello' : LEGACY_HELLO_COMMAND]: 1,
346
+ ...(isAwaitable && topologyVersion
347
+ ? { maxAwaitTimeMS, topologyVersion: makeTopologyVersion(topologyVersion) }
348
+ : {})
349
+ };
350
+
351
+ const options = isAwaitable
352
+ ? {
353
+ socketTimeoutMS: connectTimeoutMS ? connectTimeoutMS + maxAwaitTimeMS : 0,
354
+ exhaustAllowed: true
355
+ }
356
+ : { socketTimeoutMS: connectTimeoutMS };
357
+
358
+ if (isAwaitable && monitor.rttPinger == null) {
359
+ monitor.rttPinger = new RTTPinger(monitor);
360
+ }
361
+
362
+ // Record new start time before sending handshake
363
+ start = processTimeMS();
364
+
365
+ if (isAwaitable) {
366
+ awaited = true;
367
+ return connection.exhaustCommand(ns('admin.$cmd'), cmd, options, (error, hello) => {
368
+ if (error) return onHeartbeatFailed(error);
369
+ return onHeartbeatSucceeded(hello);
370
+ });
371
+ }
372
+
373
+ awaited = false;
374
+ connection
375
+ .command(ns('admin.$cmd'), cmd, options)
376
+ .then(onHeartbeatSucceeded, onHeartbeatFailed);
377
+
378
+ return;
379
+ }
380
+
381
+ // connecting does an implicit `hello`
382
+ (async () => {
383
+ const socket = await makeSocket(monitor.connectOptions);
384
+ const connection = makeConnection(monitor.connectOptions, socket);
385
+ // The start time is after socket creation but before the handshake
386
+ start = processTimeMS();
387
+ try {
388
+ await performInitialHandshake(connection, monitor.connectOptions);
389
+ return connection;
390
+ } catch (error) {
391
+ connection.destroy();
392
+ throw error;
393
+ }
394
+ })().then(
395
+ connection => {
396
+ if (isInCloseState(monitor)) {
397
+ connection.destroy();
398
+ return;
399
+ }
400
+ const duration = calculateDurationInMs(start);
401
+ monitor.addRttSample(duration);
402
+
403
+ monitor.connection = connection;
404
+ monitor.emitAndLogHeartbeat(
405
+ Server.SERVER_HEARTBEAT_SUCCEEDED,
406
+ monitor.server.topology.s.id,
407
+ connection.hello?.connectionId,
408
+ new ServerHeartbeatSucceededEvent(
409
+ monitor.address,
410
+ duration,
411
+ connection.hello,
412
+ useStreamingProtocol(monitor, connection.hello?.topologyVersion)
413
+ )
414
+ );
415
+
416
+ callback(undefined, connection.hello);
417
+ },
418
+ error => {
419
+ monitor.connection = null;
420
+ awaited = false;
421
+ onHeartbeatFailed(error);
422
+ }
423
+ );
424
+ }
425
+
426
+ function monitorServer(monitor: Monitor) {
427
+ return (callback: Callback) => {
428
+ if (monitor.s.state === STATE_MONITORING) {
429
+ queueMicrotask(callback);
430
+ return;
431
+ }
432
+ stateTransition(monitor, STATE_MONITORING);
433
+ function done() {
434
+ if (!isInCloseState(monitor)) {
435
+ stateTransition(monitor, STATE_IDLE);
436
+ }
437
+
438
+ callback();
439
+ }
440
+
441
+ checkServer(monitor, (err, hello) => {
442
+ if (err) {
443
+ // otherwise an error occurred on initial discovery, also bail
444
+ if (monitor.server.description.type === ServerType.Unknown) {
445
+ return done();
446
+ }
447
+ }
448
+
449
+ // if the check indicates streaming is supported, immediately reschedule monitoring
450
+ if (useStreamingProtocol(monitor, hello?.topologyVersion)) {
451
+ setTimeout(() => {
452
+ if (!isInCloseState(monitor)) {
453
+ monitor.monitorId?.wake();
454
+ }
455
+ }, 0);
456
+ }
457
+
458
+ done();
459
+ });
460
+ };
461
+ }
462
+
463
+ function makeTopologyVersion(tv: TopologyVersion) {
464
+ return {
465
+ processId: tv.processId,
466
+ // tests mock counter as just number, but in a real situation counter should always be a Long
467
+ // TODO(NODE-2674): Preserve int64 sent from MongoDB
468
+ counter: Long.isLong(tv.counter) ? tv.counter : Long.fromNumber(tv.counter)
469
+ };
470
+ }
471
+
472
+ /** @internal */
473
+ export interface RTTPingerOptions extends ConnectionOptions {
474
+ heartbeatFrequencyMS: number;
475
+ }
476
+
477
+ /** @internal */
478
+ export class RTTPinger {
479
+ connection?: Connection;
480
+ /** @internal */
481
+ cancellationToken: CancellationToken;
482
+ /** @internal */
483
+ monitorId: NodeJS.Timeout;
484
+ /** @internal */
485
+ monitor: Monitor;
486
+ closed: boolean;
487
+ /** @internal */
488
+ latestRtt?: number;
489
+
490
+ constructor(monitor: Monitor) {
491
+ this.connection = undefined;
492
+ this.cancellationToken = monitor.cancellationToken;
493
+ this.closed = false;
494
+ this.monitor = monitor;
495
+ this.latestRtt = monitor.latestRtt ?? undefined;
496
+
497
+ const heartbeatFrequencyMS = monitor.options.heartbeatFrequencyMS;
498
+ this.monitorId = setTimeout(() => this.measureRoundTripTime(), heartbeatFrequencyMS);
499
+ }
500
+
501
+ get roundTripTime(): number {
502
+ return this.monitor.roundTripTime;
503
+ }
504
+
505
+ get minRoundTripTime(): number {
506
+ return this.monitor.minRoundTripTime;
507
+ }
508
+
509
+ close(): void {
510
+ this.closed = true;
511
+ clearTimeout(this.monitorId);
512
+
513
+ this.connection?.destroy();
514
+ this.connection = undefined;
515
+ }
516
+
517
+ private measureAndReschedule(start: number, conn?: Connection) {
518
+ if (this.closed) {
519
+ conn?.destroy();
520
+ return;
521
+ }
522
+
523
+ if (this.connection == null) {
524
+ this.connection = conn;
525
+ }
526
+
527
+ this.latestRtt = calculateDurationInMs(start);
528
+ this.monitorId = setTimeout(
529
+ () => this.measureRoundTripTime(),
530
+ this.monitor.options.heartbeatFrequencyMS
531
+ );
532
+ }
533
+
534
+ private measureRoundTripTime() {
535
+ const start = processTimeMS();
536
+
537
+ if (this.closed) {
538
+ return;
539
+ }
540
+
541
+ const connection = this.connection;
542
+ if (connection == null) {
543
+ connect(this.monitor.connectOptions).then(
544
+ connection => {
545
+ this.measureAndReschedule(start, connection);
546
+ },
547
+ () => {
548
+ this.connection = undefined;
549
+ }
550
+ );
551
+ return;
552
+ }
553
+
554
+ const commandName =
555
+ connection.serverApi?.version || connection.helloOk ? 'hello' : LEGACY_HELLO_COMMAND;
556
+
557
+ connection.command(ns('admin.$cmd'), { [commandName]: 1 }, undefined).then(
558
+ () => this.measureAndReschedule(start),
559
+ () => {
560
+ this.connection?.destroy();
561
+ this.connection = undefined;
562
+ return;
563
+ }
564
+ );
565
+ }
566
+ }
567
+
568
+ /**
569
+ * @internal
570
+ */
571
+ export interface MonitorIntervalOptions {
572
+ /** The interval to execute a method on */
573
+ heartbeatFrequencyMS: number;
574
+ /** A minimum interval that must elapse before the method is called */
575
+ minHeartbeatFrequencyMS: number;
576
+ /** Whether the method should be called immediately when the interval is started */
577
+ immediate: boolean;
578
+ }
579
+
580
+ /**
581
+ * @internal
582
+ */
583
+ export class MonitorInterval {
584
+ fn: (callback: Callback) => void;
585
+ timerId: NodeJS.Timeout | undefined;
586
+ lastExecutionEnded: number;
587
+ isExpeditedCallToFnScheduled = false;
588
+ stopped = false;
589
+ isExecutionInProgress = false;
590
+ hasExecutedOnce = false;
591
+
592
+ heartbeatFrequencyMS: number;
593
+ minHeartbeatFrequencyMS: number;
594
+
595
+ constructor(fn: (callback: Callback) => void, options: Partial<MonitorIntervalOptions> = {}) {
596
+ this.fn = fn;
597
+ this.lastExecutionEnded = -Infinity;
598
+
599
+ this.heartbeatFrequencyMS = options.heartbeatFrequencyMS ?? 1000;
600
+ this.minHeartbeatFrequencyMS = options.minHeartbeatFrequencyMS ?? 500;
601
+
602
+ if (options.immediate) {
603
+ this._executeAndReschedule();
604
+ } else {
605
+ this._reschedule(undefined);
606
+ }
607
+ }
608
+
609
+ wake() {
610
+ const currentTime = processTimeMS();
611
+ const timeSinceLastCall = currentTime - this.lastExecutionEnded;
612
+
613
+ // TODO(NODE-4674): Add error handling and logging to the monitor
614
+ if (timeSinceLastCall < 0) {
615
+ return this._executeAndReschedule();
616
+ }
617
+
618
+ if (this.isExecutionInProgress) {
619
+ return;
620
+ }
621
+
622
+ // debounce multiple calls to wake within the `minInterval`
623
+ if (this.isExpeditedCallToFnScheduled) {
624
+ return;
625
+ }
626
+
627
+ // reschedule a call as soon as possible, ensuring the call never happens
628
+ // faster than the `minInterval`
629
+ if (timeSinceLastCall < this.minHeartbeatFrequencyMS) {
630
+ this.isExpeditedCallToFnScheduled = true;
631
+ this._reschedule(this.minHeartbeatFrequencyMS - timeSinceLastCall);
632
+ return;
633
+ }
634
+
635
+ this._executeAndReschedule();
636
+ }
637
+
638
+ stop() {
639
+ this.stopped = true;
640
+ if (this.timerId) {
641
+ clearTimeout(this.timerId);
642
+ this.timerId = undefined;
643
+ }
644
+
645
+ this.lastExecutionEnded = -Infinity;
646
+ this.isExpeditedCallToFnScheduled = false;
647
+ }
648
+
649
+ toString() {
650
+ return JSON.stringify(this);
651
+ }
652
+
653
+ toJSON() {
654
+ const currentTime = processTimeMS();
655
+ const timeSinceLastCall = currentTime - this.lastExecutionEnded;
656
+ return {
657
+ timerId: this.timerId != null ? 'set' : 'cleared',
658
+ lastCallTime: this.lastExecutionEnded,
659
+ isExpeditedCheckScheduled: this.isExpeditedCallToFnScheduled,
660
+ stopped: this.stopped,
661
+ heartbeatFrequencyMS: this.heartbeatFrequencyMS,
662
+ minHeartbeatFrequencyMS: this.minHeartbeatFrequencyMS,
663
+ currentTime,
664
+ timeSinceLastCall
665
+ };
666
+ }
667
+
668
+ private _reschedule(ms?: number) {
669
+ if (this.stopped) return;
670
+ if (this.timerId) {
671
+ clearTimeout(this.timerId);
672
+ }
673
+
674
+ this.timerId = setTimeout(this._executeAndReschedule, ms || this.heartbeatFrequencyMS);
675
+ }
676
+
677
+ private _executeAndReschedule = () => {
678
+ if (this.stopped) return;
679
+ if (this.timerId) {
680
+ clearTimeout(this.timerId);
681
+ }
682
+
683
+ this.isExpeditedCallToFnScheduled = false;
684
+ this.isExecutionInProgress = true;
685
+
686
+ this.fn(() => {
687
+ this.lastExecutionEnded = processTimeMS();
688
+ this.isExecutionInProgress = false;
689
+ this._reschedule(this.heartbeatFrequencyMS);
690
+ });
691
+ };
692
+ }
693
+
694
+ /** @internal
695
+ * This class implements the RTT sampling logic specified for [CSOT](https://github.com/mongodb/specifications/blob/bbb335e60cd7ea1e0f7cd9a9443cb95fc9d3b64d/source/client-side-operations-timeout/client-side-operations-timeout.md#drivers-use-minimum-rtt-to-short-circuit-operations)
696
+ *
697
+ * This is implemented as a [circular buffer](https://en.wikipedia.org/wiki/Circular_buffer) keeping
698
+ * the most recent `windowSize` samples
699
+ * */
700
+ export class RTTSampler {
701
+ /** Index of the next slot to be overwritten */
702
+ private writeIndex: number;
703
+ private length: number;
704
+ private rttSamples: Float64Array;
705
+
706
+ constructor(windowSize = 10) {
707
+ this.rttSamples = new Float64Array(windowSize);
708
+ this.length = 0;
709
+ this.writeIndex = 0;
710
+ }
711
+
712
+ /**
713
+ * Adds an rtt sample to the end of the circular buffer
714
+ * When `windowSize` samples have been collected, `addSample` overwrites the least recently added
715
+ * sample
716
+ */
717
+ addSample(sample: number) {
718
+ this.rttSamples[this.writeIndex++] = sample;
719
+ if (this.length < this.rttSamples.length) {
720
+ this.length++;
721
+ }
722
+
723
+ this.writeIndex %= this.rttSamples.length;
724
+ }
725
+
726
+ /**
727
+ * When \< 2 samples have been collected, returns 0
728
+ * Otherwise computes the minimum value samples contained in the buffer
729
+ */
730
+ min(): number {
731
+ if (this.length < 2) return 0;
732
+ let min = this.rttSamples[0];
733
+ for (let i = 1; i < this.length; i++) {
734
+ if (this.rttSamples[i] < min) min = this.rttSamples[i];
735
+ }
736
+
737
+ return min;
738
+ }
739
+
740
+ /**
741
+ * Returns mean of samples contained in the buffer
742
+ */
743
+ average(): number {
744
+ if (this.length === 0) return 0;
745
+ let sum = 0;
746
+ for (let i = 0; i < this.length; i++) {
747
+ sum += this.rttSamples[i];
748
+ }
749
+
750
+ return sum / this.length;
751
+ }
752
+
753
+ /**
754
+ * Returns most recently inserted element in the buffer
755
+ * Returns null if the buffer is empty
756
+ * */
757
+ get last(): number | null {
758
+ if (this.length === 0) return null;
759
+ return this.rttSamples[this.writeIndex === 0 ? this.length - 1 : this.writeIndex - 1];
760
+ }
761
+
762
+ /**
763
+ * Clear the buffer
764
+ * NOTE: this does not overwrite the data held in the internal array, just the pointers into
765
+ * this array
766
+ */
767
+ clear() {
768
+ this.length = 0;
769
+ this.writeIndex = 0;
770
+ }
771
+ }