mongodb 6.10.0 → 6.11.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 (228) hide show
  1. package/README.md +2 -0
  2. package/lib/admin.js +3 -2
  3. package/lib/admin.js.map +1 -1
  4. package/lib/beta.d.ts +562 -45
  5. package/lib/bulk/common.js +4 -4
  6. package/lib/bulk/common.js.map +1 -1
  7. package/lib/change_stream.js +111 -51
  8. package/lib/change_stream.js.map +1 -1
  9. package/lib/client-side-encryption/auto_encrypter.js +8 -5
  10. package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
  11. package/lib/client-side-encryption/client_encryption.js +48 -18
  12. package/lib/client-side-encryption/client_encryption.js.map +1 -1
  13. package/lib/client-side-encryption/state_machine.js +43 -29
  14. package/lib/client-side-encryption/state_machine.js.map +1 -1
  15. package/lib/cmap/auth/mongo_credentials.js +5 -2
  16. package/lib/cmap/auth/mongo_credentials.js.map +1 -1
  17. package/lib/cmap/auth/mongodb_aws.js +1 -1
  18. package/lib/cmap/auth/mongodb_aws.js.map +1 -1
  19. package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js +38 -0
  20. package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js.map +1 -0
  21. package/lib/cmap/auth/mongodb_oidc.js +2 -0
  22. package/lib/cmap/auth/mongodb_oidc.js.map +1 -1
  23. package/lib/cmap/connect.js +13 -1
  24. package/lib/cmap/connect.js.map +1 -1
  25. package/lib/cmap/connection.js +75 -17
  26. package/lib/cmap/connection.js.map +1 -1
  27. package/lib/cmap/connection_pool.js +14 -12
  28. package/lib/cmap/connection_pool.js.map +1 -1
  29. package/lib/cmap/wire_protocol/on_data.js +5 -1
  30. package/lib/cmap/wire_protocol/on_data.js.map +1 -1
  31. package/lib/cmap/wire_protocol/responses.js +30 -0
  32. package/lib/cmap/wire_protocol/responses.js.map +1 -1
  33. package/lib/collection.js +62 -3
  34. package/lib/collection.js.map +1 -1
  35. package/lib/connection_string.js +2 -0
  36. package/lib/connection_string.js.map +1 -1
  37. package/lib/cursor/abstract_cursor.js +221 -38
  38. package/lib/cursor/abstract_cursor.js.map +1 -1
  39. package/lib/cursor/aggregation_cursor.js +29 -7
  40. package/lib/cursor/aggregation_cursor.js.map +1 -1
  41. package/lib/cursor/change_stream_cursor.js +2 -2
  42. package/lib/cursor/change_stream_cursor.js.map +1 -1
  43. package/lib/cursor/client_bulk_write_cursor.js +1 -1
  44. package/lib/cursor/client_bulk_write_cursor.js.map +1 -1
  45. package/lib/cursor/find_cursor.js +18 -8
  46. package/lib/cursor/find_cursor.js.map +1 -1
  47. package/lib/cursor/list_collections_cursor.js +1 -1
  48. package/lib/cursor/list_collections_cursor.js.map +1 -1
  49. package/lib/cursor/list_indexes_cursor.js +1 -1
  50. package/lib/cursor/list_indexes_cursor.js.map +1 -1
  51. package/lib/cursor/run_command_cursor.js +6 -4
  52. package/lib/cursor/run_command_cursor.js.map +1 -1
  53. package/lib/db.js +63 -3
  54. package/lib/db.js.map +1 -1
  55. package/lib/error.js +34 -9
  56. package/lib/error.js.map +1 -1
  57. package/lib/explain.js +57 -1
  58. package/lib/explain.js.map +1 -1
  59. package/lib/gridfs/download.js +31 -3
  60. package/lib/gridfs/download.js.map +1 -1
  61. package/lib/gridfs/index.js +49 -14
  62. package/lib/gridfs/index.js.map +1 -1
  63. package/lib/gridfs/upload.js +80 -22
  64. package/lib/gridfs/upload.js.map +1 -1
  65. package/lib/index.js +9 -5
  66. package/lib/index.js.map +1 -1
  67. package/lib/mongo_client.js +70 -1
  68. package/lib/mongo_client.js.map +1 -1
  69. package/lib/operations/aggregate.js +2 -2
  70. package/lib/operations/aggregate.js.map +1 -1
  71. package/lib/operations/bulk_write.js +7 -2
  72. package/lib/operations/bulk_write.js.map +1 -1
  73. package/lib/operations/client_bulk_write/client_bulk_write.js +3 -3
  74. package/lib/operations/client_bulk_write/client_bulk_write.js.map +1 -1
  75. package/lib/operations/client_bulk_write/executor.js +14 -3
  76. package/lib/operations/client_bulk_write/executor.js.map +1 -1
  77. package/lib/operations/command.js +5 -2
  78. package/lib/operations/command.js.map +1 -1
  79. package/lib/operations/count.js +2 -2
  80. package/lib/operations/count.js.map +1 -1
  81. package/lib/operations/create_collection.js +8 -7
  82. package/lib/operations/create_collection.js.map +1 -1
  83. package/lib/operations/delete.js +6 -6
  84. package/lib/operations/delete.js.map +1 -1
  85. package/lib/operations/distinct.js +2 -2
  86. package/lib/operations/distinct.js.map +1 -1
  87. package/lib/operations/drop.js +8 -8
  88. package/lib/operations/drop.js.map +1 -1
  89. package/lib/operations/estimated_document_count.js +2 -2
  90. package/lib/operations/estimated_document_count.js.map +1 -1
  91. package/lib/operations/execute_operation.js +16 -10
  92. package/lib/operations/execute_operation.js.map +1 -1
  93. package/lib/operations/find.js +6 -3
  94. package/lib/operations/find.js.map +1 -1
  95. package/lib/operations/find_and_modify.js +2 -2
  96. package/lib/operations/find_and_modify.js.map +1 -1
  97. package/lib/operations/get_more.js +2 -1
  98. package/lib/operations/get_more.js.map +1 -1
  99. package/lib/operations/indexes.js +6 -6
  100. package/lib/operations/indexes.js.map +1 -1
  101. package/lib/operations/insert.js +6 -6
  102. package/lib/operations/insert.js.map +1 -1
  103. package/lib/operations/kill_cursors.js +5 -2
  104. package/lib/operations/kill_cursors.js.map +1 -1
  105. package/lib/operations/list_collections.js +2 -2
  106. package/lib/operations/list_collections.js.map +1 -1
  107. package/lib/operations/list_databases.js +2 -2
  108. package/lib/operations/list_databases.js.map +1 -1
  109. package/lib/operations/operation.js.map +1 -1
  110. package/lib/operations/profiling_level.js +2 -2
  111. package/lib/operations/profiling_level.js.map +1 -1
  112. package/lib/operations/remove_user.js +2 -2
  113. package/lib/operations/remove_user.js.map +1 -1
  114. package/lib/operations/rename.js +2 -2
  115. package/lib/operations/rename.js.map +1 -1
  116. package/lib/operations/run_command.js +6 -4
  117. package/lib/operations/run_command.js.map +1 -1
  118. package/lib/operations/search_indexes/create.js +5 -2
  119. package/lib/operations/search_indexes/create.js.map +1 -1
  120. package/lib/operations/search_indexes/drop.js +2 -2
  121. package/lib/operations/search_indexes/drop.js.map +1 -1
  122. package/lib/operations/search_indexes/update.js +2 -2
  123. package/lib/operations/search_indexes/update.js.map +1 -1
  124. package/lib/operations/set_profiling_level.js +2 -2
  125. package/lib/operations/set_profiling_level.js.map +1 -1
  126. package/lib/operations/stats.js +2 -2
  127. package/lib/operations/stats.js.map +1 -1
  128. package/lib/operations/update.js +8 -8
  129. package/lib/operations/update.js.map +1 -1
  130. package/lib/operations/validate_collection.js +2 -2
  131. package/lib/operations/validate_collection.js.map +1 -1
  132. package/lib/read_concern.js +1 -1
  133. package/lib/sdam/common.js +0 -7
  134. package/lib/sdam/common.js.map +1 -1
  135. package/lib/sdam/server.js +4 -1
  136. package/lib/sdam/server.js.map +1 -1
  137. package/lib/sdam/server_description.js +4 -2
  138. package/lib/sdam/server_description.js.map +1 -1
  139. package/lib/sdam/server_selection.js +5 -2
  140. package/lib/sdam/server_selection.js.map +1 -1
  141. package/lib/sdam/topology.js +38 -15
  142. package/lib/sdam/topology.js.map +1 -1
  143. package/lib/sessions.js +157 -98
  144. package/lib/sessions.js.map +1 -1
  145. package/lib/timeout.js +231 -16
  146. package/lib/timeout.js.map +1 -1
  147. package/lib/utils.js +36 -19
  148. package/lib/utils.js.map +1 -1
  149. package/lib/write_concern.js.map +1 -1
  150. package/mongodb.d.ts +562 -45
  151. package/package.json +17 -16
  152. package/src/admin.ts +6 -2
  153. package/src/bulk/common.ts +17 -5
  154. package/src/change_stream.ts +127 -52
  155. package/src/client-side-encryption/auto_encrypter.ts +12 -5
  156. package/src/client-side-encryption/client_encryption.ts +103 -20
  157. package/src/client-side-encryption/state_machine.ts +66 -32
  158. package/src/cmap/auth/mongo_credentials.ts +6 -3
  159. package/src/cmap/auth/mongodb_aws.ts +1 -1
  160. package/src/cmap/auth/mongodb_oidc/k8s_machine_workflow.ts +38 -0
  161. package/src/cmap/auth/mongodb_oidc.ts +3 -1
  162. package/src/cmap/connect.ts +18 -1
  163. package/src/cmap/connection.ts +105 -17
  164. package/src/cmap/connection_pool.ts +15 -17
  165. package/src/cmap/handshake/client_metadata.ts +1 -1
  166. package/src/cmap/wire_protocol/on_data.ts +11 -1
  167. package/src/cmap/wire_protocol/responses.ts +35 -1
  168. package/src/collection.ts +81 -9
  169. package/src/connection_string.ts +2 -0
  170. package/src/cursor/abstract_cursor.ts +287 -39
  171. package/src/cursor/aggregation_cursor.ts +54 -8
  172. package/src/cursor/change_stream_cursor.ts +6 -2
  173. package/src/cursor/client_bulk_write_cursor.ts +6 -2
  174. package/src/cursor/find_cursor.ts +40 -9
  175. package/src/cursor/list_collections_cursor.ts +1 -1
  176. package/src/cursor/list_indexes_cursor.ts +1 -1
  177. package/src/cursor/run_command_cursor.ts +50 -5
  178. package/src/db.ts +75 -7
  179. package/src/error.ts +33 -8
  180. package/src/explain.ts +85 -0
  181. package/src/gridfs/download.ts +43 -4
  182. package/src/gridfs/index.ts +64 -16
  183. package/src/gridfs/upload.ts +153 -45
  184. package/src/index.ts +27 -5
  185. package/src/mongo_client.ts +76 -4
  186. package/src/operations/aggregate.ts +10 -2
  187. package/src/operations/bulk_write.ts +9 -2
  188. package/src/operations/client_bulk_write/client_bulk_write.ts +11 -3
  189. package/src/operations/client_bulk_write/executor.ts +15 -3
  190. package/src/operations/command.ts +18 -8
  191. package/src/operations/count.ts +10 -3
  192. package/src/operations/create_collection.ts +14 -7
  193. package/src/operations/delete.ts +15 -6
  194. package/src/operations/distinct.ts +7 -2
  195. package/src/operations/drop.ts +18 -8
  196. package/src/operations/estimated_document_count.ts +7 -2
  197. package/src/operations/execute_operation.ts +22 -13
  198. package/src/operations/find.ts +17 -5
  199. package/src/operations/find_and_modify.ts +7 -2
  200. package/src/operations/get_more.ts +4 -1
  201. package/src/operations/indexes.ts +20 -7
  202. package/src/operations/insert.ts +13 -6
  203. package/src/operations/kill_cursors.ts +10 -2
  204. package/src/operations/list_collections.ts +10 -1
  205. package/src/operations/list_databases.ts +9 -2
  206. package/src/operations/operation.ts +16 -2
  207. package/src/operations/profiling_level.ts +7 -2
  208. package/src/operations/remove_user.ts +7 -2
  209. package/src/operations/rename.ts +7 -2
  210. package/src/operations/run_command.ts +23 -4
  211. package/src/operations/search_indexes/create.ts +10 -2
  212. package/src/operations/search_indexes/drop.ts +7 -2
  213. package/src/operations/search_indexes/update.ts +7 -2
  214. package/src/operations/set_profiling_level.ts +4 -2
  215. package/src/operations/stats.ts +7 -2
  216. package/src/operations/update.ts +16 -8
  217. package/src/operations/validate_collection.ts +7 -2
  218. package/src/read_concern.ts +1 -1
  219. package/src/sdam/common.ts +0 -11
  220. package/src/sdam/server.ts +14 -4
  221. package/src/sdam/server_description.ts +6 -2
  222. package/src/sdam/server_selection.ts +5 -2
  223. package/src/sdam/topology.ts +43 -27
  224. package/src/sessions.ts +206 -120
  225. package/src/timeout.ts +327 -23
  226. package/src/transactions.ts +1 -1
  227. package/src/utils.ts +47 -30
  228. package/src/write_concern.ts +6 -3
@@ -2,10 +2,12 @@ import type { ObjectId } from '../bson';
2
2
  import type { Collection } from '../collection';
3
3
  import type { FindCursor } from '../cursor/find_cursor';
4
4
  import type { Db } from '../db';
5
- import { MongoRuntimeError } from '../error';
5
+ import { MongoOperationTimeoutError, MongoRuntimeError } from '../error';
6
6
  import { type Filter, TypedEventEmitter } from '../mongo_types';
7
7
  import type { ReadPreference } from '../read_preference';
8
8
  import type { Sort } from '../sort';
9
+ import { CSOTTimeoutContext } from '../timeout';
10
+ import { resolveOptions } from '../utils';
9
11
  import { WriteConcern, type WriteConcernOptions } from '../write_concern';
10
12
  import type { FindOptions } from './../operations/find';
11
13
  import {
@@ -36,7 +38,11 @@ export interface GridFSBucketOptions extends WriteConcernOptions {
36
38
  chunkSizeBytes?: number;
37
39
  /** Read preference to be passed to read operations */
38
40
  readPreference?: ReadPreference;
39
- /** @internal TODO(NODE-5688): make this public */
41
+ /**
42
+ * @experimental
43
+ * Specifies the lifetime duration of a gridFS stream. If any async operations are in progress
44
+ * when this timeout expires, the stream will throw a timeout error.
45
+ */
40
46
  timeoutMS?: number;
41
47
  }
42
48
 
@@ -48,6 +54,7 @@ export interface GridFSBucketPrivate {
48
54
  chunkSizeBytes: number;
49
55
  readPreference?: ReadPreference;
50
56
  writeConcern: WriteConcern | undefined;
57
+ timeoutMS?: number;
51
58
  };
52
59
  _chunksCollection: Collection<GridFSChunk>;
53
60
  _filesCollection: Collection<GridFSFile>;
@@ -81,11 +88,11 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
81
88
  constructor(db: Db, options?: GridFSBucketOptions) {
82
89
  super();
83
90
  this.setMaxListeners(0);
84
- const privateOptions = {
91
+ const privateOptions = resolveOptions(db, {
85
92
  ...DEFAULT_GRIDFS_BUCKET_OPTIONS,
86
93
  ...options,
87
94
  writeConcern: WriteConcern.fromOptions(options)
88
- };
95
+ });
89
96
  this.s = {
90
97
  db,
91
98
  options: privateOptions,
@@ -109,7 +116,10 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
109
116
  filename: string,
110
117
  options?: GridFSBucketWriteStreamOptions
111
118
  ): GridFSBucketWriteStream {
112
- return new GridFSBucketWriteStream(this, filename, options);
119
+ return new GridFSBucketWriteStream(this, filename, {
120
+ timeoutMS: this.s.options.timeoutMS,
121
+ ...options
122
+ });
113
123
  }
114
124
 
115
125
  /**
@@ -122,7 +132,11 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
122
132
  filename: string,
123
133
  options?: GridFSBucketWriteStreamOptions
124
134
  ): GridFSBucketWriteStream {
125
- return new GridFSBucketWriteStream(this, filename, { ...options, id });
135
+ return new GridFSBucketWriteStream(this, filename, {
136
+ timeoutMS: this.s.options.timeoutMS,
137
+ ...options,
138
+ id
139
+ });
126
140
  }
127
141
 
128
142
  /** Returns a readable stream (GridFSBucketReadStream) for streaming file data from GridFS. */
@@ -135,7 +149,7 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
135
149
  this.s._filesCollection,
136
150
  this.s.options.readPreference,
137
151
  { _id: id },
138
- options
152
+ { timeoutMS: this.s.options.timeoutMS, ...options }
139
153
  );
140
154
  }
141
155
 
@@ -144,11 +158,27 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
144
158
  *
145
159
  * @param id - The id of the file doc
146
160
  */
147
- async delete(id: ObjectId): Promise<void> {
148
- const { deletedCount } = await this.s._filesCollection.deleteOne({ _id: id });
161
+ async delete(id: ObjectId, options?: { timeoutMS: number }): Promise<void> {
162
+ const { timeoutMS } = resolveOptions(this.s.db, options);
163
+ let timeoutContext: CSOTTimeoutContext | undefined = undefined;
149
164
 
165
+ if (timeoutMS) {
166
+ timeoutContext = new CSOTTimeoutContext({
167
+ timeoutMS,
168
+ serverSelectionTimeoutMS: this.s.db.client.s.options.serverSelectionTimeoutMS
169
+ });
170
+ }
171
+
172
+ const { deletedCount } = await this.s._filesCollection.deleteOne(
173
+ { _id: id },
174
+ { timeoutMS: timeoutContext?.remainingTimeMS }
175
+ );
176
+
177
+ const remainingTimeMS = timeoutContext?.remainingTimeMS;
178
+ if (remainingTimeMS != null && remainingTimeMS <= 0)
179
+ throw new MongoOperationTimeoutError(`Timed out after ${timeoutMS}ms`);
150
180
  // Delete orphaned chunks before returning FileNotFound
151
- await this.s._chunksCollection.deleteMany({ files_id: id });
181
+ await this.s._chunksCollection.deleteMany({ files_id: id }, { timeoutMS: remainingTimeMS });
152
182
 
153
183
  if (deletedCount === 0) {
154
184
  // TODO(NODE-3483): Replace with more appropriate error
@@ -188,7 +218,7 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
188
218
  this.s._filesCollection,
189
219
  this.s.options.readPreference,
190
220
  { filename },
191
- { ...options, sort, skip }
221
+ { timeoutMS: this.s.options.timeoutMS, ...options, sort, skip }
192
222
  );
193
223
  }
194
224
 
@@ -198,18 +228,36 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
198
228
  * @param id - the id of the file to rename
199
229
  * @param filename - new name for the file
200
230
  */
201
- async rename(id: ObjectId, filename: string): Promise<void> {
231
+ async rename(id: ObjectId, filename: string, options?: { timeoutMS: number }): Promise<void> {
202
232
  const filter = { _id: id };
203
233
  const update = { $set: { filename } };
204
- const { matchedCount } = await this.s._filesCollection.updateOne(filter, update);
234
+ const { matchedCount } = await this.s._filesCollection.updateOne(filter, update, options);
205
235
  if (matchedCount === 0) {
206
236
  throw new MongoRuntimeError(`File with id ${id} not found`);
207
237
  }
208
238
  }
209
239
 
210
240
  /** Removes this bucket's files collection, followed by its chunks collection. */
211
- async drop(): Promise<void> {
212
- await this.s._filesCollection.drop();
213
- await this.s._chunksCollection.drop();
241
+ async drop(options?: { timeoutMS: number }): Promise<void> {
242
+ const { timeoutMS } = resolveOptions(this.s.db, options);
243
+ let timeoutContext: CSOTTimeoutContext | undefined = undefined;
244
+
245
+ if (timeoutMS) {
246
+ timeoutContext = new CSOTTimeoutContext({
247
+ timeoutMS,
248
+ serverSelectionTimeoutMS: this.s.db.client.s.options.serverSelectionTimeoutMS
249
+ });
250
+ }
251
+
252
+ if (timeoutContext) {
253
+ await this.s._filesCollection.drop({ timeoutMS: timeoutContext.remainingTimeMS });
254
+ const remainingTimeMS = timeoutContext.getRemainingTimeMSOrThrow(
255
+ `Timed out after ${timeoutMS}ms`
256
+ );
257
+ await this.s._chunksCollection.drop({ timeoutMS: remainingTimeMS });
258
+ } else {
259
+ await this.s._filesCollection.drop();
260
+ await this.s._chunksCollection.drop();
261
+ }
214
262
  }
215
263
  }
@@ -2,8 +2,15 @@ import { Writable } from 'stream';
2
2
 
3
3
  import { type Document, ObjectId } from '../bson';
4
4
  import type { Collection } from '../collection';
5
- import { MongoAPIError, MONGODB_ERROR_CODES, MongoError } from '../error';
6
- import { type Callback, squashError } from '../utils';
5
+ import { CursorTimeoutMode } from '../cursor/abstract_cursor';
6
+ import {
7
+ MongoAPIError,
8
+ MONGODB_ERROR_CODES,
9
+ MongoError,
10
+ MongoOperationTimeoutError
11
+ } from '../error';
12
+ import { CSOTTimeoutContext } from '../timeout';
13
+ import { type Callback, resolveTimeoutOptions, squashError } from '../utils';
7
14
  import type { WriteConcernOptions } from '../write_concern';
8
15
  import { WriteConcern } from './../write_concern';
9
16
  import type { GridFSFile } from './download';
@@ -35,7 +42,10 @@ export interface GridFSBucketWriteStreamOptions extends WriteConcernOptions {
35
42
  * @deprecated Will be removed in the next major version. Add an aliases field to the metadata document instead.
36
43
  */
37
44
  aliases?: string[];
38
- /** @internal TODO(NODE-5688): make this public */
45
+ /**
46
+ * @experimental
47
+ * Specifies the time an operation will run until it throws a timeout error
48
+ */
39
49
  timeoutMS?: number;
40
50
  }
41
51
 
@@ -97,6 +107,8 @@ export class GridFSBucketWriteStream extends Writable {
97
107
  * ```
98
108
  */
99
109
  gridFSFile: GridFSFile | null = null;
110
+ /** @internal */
111
+ timeoutContext?: CSOTTimeoutContext;
100
112
 
101
113
  /**
102
114
  * @param bucket - Handle for this stream's corresponding bucket
@@ -131,14 +143,12 @@ export class GridFSBucketWriteStream extends Writable {
131
143
  aborted: false
132
144
  };
133
145
 
134
- if (!this.bucket.s.calledOpenUploadStream) {
135
- this.bucket.s.calledOpenUploadStream = true;
136
-
137
- checkIndexes(this).then(() => {
138
- this.bucket.s.checkedIndexes = true;
139
- this.bucket.emit('index');
140
- }, squashError);
141
- }
146
+ if (options.timeoutMS != null)
147
+ this.timeoutContext = new CSOTTimeoutContext({
148
+ timeoutMS: options.timeoutMS,
149
+ serverSelectionTimeoutMS: resolveTimeoutOptions(this.bucket.s.db.client, {})
150
+ .serverSelectionTimeoutMS
151
+ });
142
152
  }
143
153
 
144
154
  /**
@@ -147,10 +157,26 @@ export class GridFSBucketWriteStream extends Writable {
147
157
  * The stream is considered constructed when the indexes are done being created
148
158
  */
149
159
  override _construct(callback: (error?: Error | null) => void): void {
150
- if (this.bucket.s.checkedIndexes) {
160
+ if (!this.bucket.s.calledOpenUploadStream) {
161
+ this.bucket.s.calledOpenUploadStream = true;
162
+
163
+ checkIndexes(this).then(
164
+ () => {
165
+ this.bucket.s.checkedIndexes = true;
166
+ this.bucket.emit('index');
167
+ callback();
168
+ },
169
+ error => {
170
+ if (error instanceof MongoOperationTimeoutError) {
171
+ return handleError(this, error, callback);
172
+ }
173
+ squashError(error);
174
+ callback();
175
+ }
176
+ );
177
+ } else {
151
178
  return process.nextTick(callback);
152
179
  }
153
- this.bucket.once('index', callback);
154
180
  }
155
181
 
156
182
  /**
@@ -194,7 +220,11 @@ export class GridFSBucketWriteStream extends Writable {
194
220
  }
195
221
 
196
222
  this.state.aborted = true;
197
- await this.chunks.deleteMany({ files_id: this.id });
223
+ const remainingTimeMS = this.timeoutContext?.getRemainingTimeMSOrThrow(
224
+ `Upload timed out after ${this.timeoutContext?.timeoutMS}ms`
225
+ );
226
+
227
+ await this.chunks.deleteMany({ files_id: this.id }, { timeoutMS: remainingTimeMS });
198
228
  }
199
229
  }
200
230
 
@@ -219,9 +249,19 @@ function createChunkDoc(filesId: ObjectId, n: number, data: Buffer): GridFSChunk
219
249
  async function checkChunksIndex(stream: GridFSBucketWriteStream): Promise<void> {
220
250
  const index = { files_id: 1, n: 1 };
221
251
 
252
+ let remainingTimeMS;
253
+ remainingTimeMS = stream.timeoutContext?.getRemainingTimeMSOrThrow(
254
+ `Upload timed out after ${stream.timeoutContext?.timeoutMS}ms`
255
+ );
256
+
222
257
  let indexes;
223
258
  try {
224
- indexes = await stream.chunks.listIndexes().toArray();
259
+ indexes = await stream.chunks
260
+ .listIndexes({
261
+ timeoutMode: remainingTimeMS != null ? CursorTimeoutMode.LIFETIME : undefined,
262
+ timeoutMS: remainingTimeMS
263
+ })
264
+ .toArray();
225
265
  } catch (error) {
226
266
  if (error instanceof MongoError && error.code === MONGODB_ERROR_CODES.NamespaceNotFound) {
227
267
  indexes = [];
@@ -239,10 +279,14 @@ async function checkChunksIndex(stream: GridFSBucketWriteStream): Promise<void>
239
279
  });
240
280
 
241
281
  if (!hasChunksIndex) {
282
+ remainingTimeMS = stream.timeoutContext?.getRemainingTimeMSOrThrow(
283
+ `Upload timed out after ${stream.timeoutContext?.timeoutMS}ms`
284
+ );
242
285
  await stream.chunks.createIndex(index, {
243
286
  ...stream.writeConcern,
244
287
  background: true,
245
- unique: true
288
+ unique: true,
289
+ timeoutMS: remainingTimeMS
246
290
  });
247
291
  }
248
292
  }
@@ -270,13 +314,28 @@ function checkDone(stream: GridFSBucketWriteStream, callback: Callback): void {
270
314
  return;
271
315
  }
272
316
 
273
- stream.files.insertOne(gridFSFile, { writeConcern: stream.writeConcern }).then(
274
- () => {
275
- stream.gridFSFile = gridFSFile;
276
- callback();
277
- },
278
- error => handleError(stream, error, callback)
279
- );
317
+ const remainingTimeMS = stream.timeoutContext?.remainingTimeMS;
318
+ if (remainingTimeMS != null && remainingTimeMS <= 0) {
319
+ return handleError(
320
+ stream,
321
+ new MongoOperationTimeoutError(
322
+ `Upload timed out after ${stream.timeoutContext?.timeoutMS}ms`
323
+ ),
324
+ callback
325
+ );
326
+ }
327
+
328
+ stream.files
329
+ .insertOne(gridFSFile, { writeConcern: stream.writeConcern, timeoutMS: remainingTimeMS })
330
+ .then(
331
+ () => {
332
+ stream.gridFSFile = gridFSFile;
333
+ callback();
334
+ },
335
+ error => {
336
+ return handleError(stream, error, callback);
337
+ }
338
+ );
280
339
  return;
281
340
  }
282
341
 
@@ -284,7 +343,16 @@ function checkDone(stream: GridFSBucketWriteStream, callback: Callback): void {
284
343
  }
285
344
 
286
345
  async function checkIndexes(stream: GridFSBucketWriteStream): Promise<void> {
287
- const doc = await stream.files.findOne({}, { projection: { _id: 1 } });
346
+ let remainingTimeMS = stream.timeoutContext?.getRemainingTimeMSOrThrow(
347
+ `Upload timed out after ${stream.timeoutContext?.timeoutMS}ms`
348
+ );
349
+ const doc = await stream.files.findOne(
350
+ {},
351
+ {
352
+ projection: { _id: 1 },
353
+ timeoutMS: remainingTimeMS
354
+ }
355
+ );
288
356
  if (doc != null) {
289
357
  // If at least one document exists assume the collection has the required index
290
358
  return;
@@ -293,8 +361,15 @@ async function checkIndexes(stream: GridFSBucketWriteStream): Promise<void> {
293
361
  const index = { filename: 1, uploadDate: 1 };
294
362
 
295
363
  let indexes;
364
+ remainingTimeMS = stream.timeoutContext?.getRemainingTimeMSOrThrow(
365
+ `Upload timed out after ${stream.timeoutContext?.timeoutMS}ms`
366
+ );
367
+ const listIndexesOptions = {
368
+ timeoutMode: remainingTimeMS != null ? CursorTimeoutMode.LIFETIME : undefined,
369
+ timeoutMS: remainingTimeMS
370
+ };
296
371
  try {
297
- indexes = await stream.files.listIndexes().toArray();
372
+ indexes = await stream.files.listIndexes(listIndexesOptions).toArray();
298
373
  } catch (error) {
299
374
  if (error instanceof MongoError && error.code === MONGODB_ERROR_CODES.NamespaceNotFound) {
300
375
  indexes = [];
@@ -312,7 +387,11 @@ async function checkIndexes(stream: GridFSBucketWriteStream): Promise<void> {
312
387
  });
313
388
 
314
389
  if (!hasFileIndex) {
315
- await stream.files.createIndex(index, { background: false });
390
+ remainingTimeMS = stream.timeoutContext?.getRemainingTimeMSOrThrow(
391
+ `Upload timed out after ${stream.timeoutContext?.timeoutMS}ms`
392
+ );
393
+
394
+ await stream.files.createIndex(index, { background: false, timeoutMS: remainingTimeMS });
316
395
  }
317
396
 
318
397
  await checkChunksIndex(stream);
@@ -386,6 +465,18 @@ function doWrite(
386
465
  let doc: GridFSChunk;
387
466
  if (spaceRemaining === 0) {
388
467
  doc = createChunkDoc(stream.id, stream.n, Buffer.from(stream.bufToStore));
468
+
469
+ const remainingTimeMS = stream.timeoutContext?.remainingTimeMS;
470
+ if (remainingTimeMS != null && remainingTimeMS <= 0) {
471
+ return handleError(
472
+ stream,
473
+ new MongoOperationTimeoutError(
474
+ `Upload timed out after ${stream.timeoutContext?.timeoutMS}ms`
475
+ ),
476
+ callback
477
+ );
478
+ }
479
+
389
480
  ++stream.state.outstandingRequests;
390
481
  ++outstandingRequests;
391
482
 
@@ -393,17 +484,21 @@ function doWrite(
393
484
  return;
394
485
  }
395
486
 
396
- stream.chunks.insertOne(doc, { writeConcern: stream.writeConcern }).then(
397
- () => {
398
- --stream.state.outstandingRequests;
399
- --outstandingRequests;
400
-
401
- if (!outstandingRequests) {
402
- checkDone(stream, callback);
487
+ stream.chunks
488
+ .insertOne(doc, { writeConcern: stream.writeConcern, timeoutMS: remainingTimeMS })
489
+ .then(
490
+ () => {
491
+ --stream.state.outstandingRequests;
492
+ --outstandingRequests;
493
+
494
+ if (!outstandingRequests) {
495
+ checkDone(stream, callback);
496
+ }
497
+ },
498
+ error => {
499
+ return handleError(stream, error, callback);
403
500
  }
404
- },
405
- error => handleError(stream, error, callback)
406
- );
501
+ );
407
502
 
408
503
  spaceRemaining = stream.chunkSizeBytes;
409
504
  stream.pos = 0;
@@ -420,8 +515,6 @@ function writeRemnant(stream: GridFSBucketWriteStream, callback: Callback): void
420
515
  return checkDone(stream, callback);
421
516
  }
422
517
 
423
- ++stream.state.outstandingRequests;
424
-
425
518
  // Create a new buffer to make sure the buffer isn't bigger than it needs
426
519
  // to be.
427
520
  const remnant = Buffer.alloc(stream.pos);
@@ -433,13 +526,28 @@ function writeRemnant(stream: GridFSBucketWriteStream, callback: Callback): void
433
526
  return;
434
527
  }
435
528
 
436
- stream.chunks.insertOne(doc, { writeConcern: stream.writeConcern }).then(
437
- () => {
438
- --stream.state.outstandingRequests;
439
- checkDone(stream, callback);
440
- },
441
- error => handleError(stream, error, callback)
442
- );
529
+ const remainingTimeMS = stream.timeoutContext?.remainingTimeMS;
530
+ if (remainingTimeMS != null && remainingTimeMS <= 0) {
531
+ return handleError(
532
+ stream,
533
+ new MongoOperationTimeoutError(
534
+ `Upload timed out after ${stream.timeoutContext?.timeoutMS}ms`
535
+ ),
536
+ callback
537
+ );
538
+ }
539
+ ++stream.state.outstandingRequests;
540
+ stream.chunks
541
+ .insertOne(doc, { writeConcern: stream.writeConcern, timeoutMS: remainingTimeMS })
542
+ .then(
543
+ () => {
544
+ --stream.state.outstandingRequests;
545
+ checkDone(stream, callback);
546
+ },
547
+ error => {
548
+ return handleError(stream, error, callback);
549
+ }
550
+ );
443
551
  }
444
552
 
445
553
  function isAborted(stream: GridFSBucketWriteStream, callback: Callback<void>): boolean {
package/src/index.ts CHANGED
@@ -10,6 +10,7 @@ import { ListCollectionsCursor } from './cursor/list_collections_cursor';
10
10
  import { ListIndexesCursor } from './cursor/list_indexes_cursor';
11
11
  import type { RunCommandCursor } from './cursor/run_command_cursor';
12
12
  import { Db } from './db';
13
+ import { ExplainableCursor } from './explain';
13
14
  import { GridFSBucket } from './gridfs';
14
15
  import { GridFSBucketReadStream } from './gridfs/download';
15
16
  import { GridFSBucketWriteStream } from './gridfs/upload';
@@ -36,7 +37,11 @@ export {
36
37
  Timestamp,
37
38
  UUID
38
39
  } from './bson';
39
- export { AnyBulkWriteOperation, BulkWriteOptions, MongoBulkWriteError } from './bulk/common';
40
+ export {
41
+ type AnyBulkWriteOperation,
42
+ type BulkWriteOptions,
43
+ MongoBulkWriteError
44
+ } from './bulk/common';
40
45
  export { ClientEncryption } from './client-side-encryption/client_encryption';
41
46
  export { ChangeStreamCursor } from './cursor/change_stream_cursor';
42
47
  export {
@@ -66,6 +71,7 @@ export {
66
71
  MongoNetworkTimeoutError,
67
72
  MongoNotConnectedError,
68
73
  MongoOIDCError,
74
+ MongoOperationTimeoutError,
69
75
  MongoParseError,
70
76
  MongoRuntimeError,
71
77
  MongoServerClosedError,
@@ -90,6 +96,7 @@ export {
90
96
  ClientSession,
91
97
  Collection,
92
98
  Db,
99
+ ExplainableCursor,
93
100
  FindCursor,
94
101
  GridFSBucket,
95
102
  GridFSBucketReadStream,
@@ -108,7 +115,7 @@ export { AutoEncryptionLoggerLevel } from './client-side-encryption/auto_encrypt
108
115
  export { GSSAPICanonicalizationValue } from './cmap/auth/gssapi';
109
116
  export { AuthMechanism } from './cmap/auth/providers';
110
117
  export { Compressor } from './cmap/wire_protocol/compression';
111
- export { CURSOR_FLAGS } from './cursor/abstract_cursor';
118
+ export { CURSOR_FLAGS, CursorTimeoutMode } from './cursor/abstract_cursor';
112
119
  export { MongoErrorLabel } from './error';
113
120
  export { ExplainVerbosity } from './explain';
114
121
  export { ServerApiVersion } from './mongo_client';
@@ -358,6 +365,7 @@ export type {
358
365
  CursorStreamOptions
359
366
  } from './cursor/abstract_cursor';
360
367
  export type {
368
+ CursorTimeoutContext,
361
369
  InitialCursorResponse,
362
370
  InternalAbstractCursorOptions
363
371
  } from './cursor/abstract_cursor';
@@ -553,7 +561,7 @@ export type {
553
561
  ReadPreferenceOptions
554
562
  } from './read_preference';
555
563
  export type { AsyncDisposable } from './resource_management';
556
- export type { ClusterTime, TimerQueue } from './sdam/common';
564
+ export type { ClusterTime } from './sdam/common';
557
565
  export type {
558
566
  Monitor,
559
567
  MonitorEvents,
@@ -566,7 +574,13 @@ export type {
566
574
  RTTSampler,
567
575
  ServerMonitoringMode
568
576
  } from './sdam/monitor';
569
- export type { Server, ServerEvents, ServerOptions, ServerPrivate } from './sdam/server';
577
+ export type {
578
+ Server,
579
+ ServerCommandOptions,
580
+ ServerEvents,
581
+ ServerOptions,
582
+ ServerPrivate
583
+ } from './sdam/server';
570
584
  export type {
571
585
  ServerDescription,
572
586
  ServerDescriptionOptions,
@@ -597,7 +611,15 @@ export type {
597
611
  WithTransactionCallback
598
612
  } from './sessions';
599
613
  export type { Sort, SortDirection, SortDirectionForCmd, SortForCmd } from './sort';
600
- export type { Timeout } from './timeout';
614
+ export type {
615
+ CSOTTimeoutContext,
616
+ CSOTTimeoutContextOptions,
617
+ LegacyTimeoutContext,
618
+ LegacyTimeoutContextOptions,
619
+ Timeout,
620
+ TimeoutContext,
621
+ TimeoutContextOptions
622
+ } from './timeout';
601
623
  export type { Transaction, TransactionOptions, TxnState } from './transactions';
602
624
  export type {
603
625
  BufferPool,