@@ -2,10 +2,12 @@ import type { ObjectId } from '../bson';
22import type { Collection } from '../collection' ;
33import type { FindCursor } from '../cursor/find_cursor' ;
44import type { Db } from '../db' ;
5- import { MongoRuntimeError } from '../error' ;
5+ import { MongoOperationTimeoutError , MongoRuntimeError } from '../error' ;
66import { type Filter , TypedEventEmitter } from '../mongo_types' ;
77import type { ReadPreference } from '../read_preference' ;
88import type { Sort } from '../sort' ;
9+ import { CSOTTimeoutContext } from '../timeout' ;
10+ import { resolveOptions } from '../utils' ;
911import { WriteConcern , type WriteConcernOptions } from '../write_concern' ;
1012import type { FindOptions } from './../operations/find' ;
1113import {
@@ -48,6 +50,7 @@ export interface GridFSBucketPrivate {
4850 chunkSizeBytes : number ;
4951 readPreference ?: ReadPreference ;
5052 writeConcern : WriteConcern | undefined ;
53+ timeoutMS ?: number ;
5154 } ;
5255 _chunksCollection : Collection < GridFSChunk > ;
5356 _filesCollection : Collection < GridFSFile > ;
@@ -81,11 +84,11 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
8184 constructor ( db : Db , options ?: GridFSBucketOptions ) {
8285 super ( ) ;
8386 this . setMaxListeners ( 0 ) ;
84- const privateOptions = {
87+ const privateOptions = resolveOptions ( db , {
8588 ...DEFAULT_GRIDFS_BUCKET_OPTIONS ,
8689 ...options ,
8790 writeConcern : WriteConcern . fromOptions ( options )
88- } ;
91+ } ) ;
8992 this . s = {
9093 db,
9194 options : privateOptions ,
@@ -109,7 +112,10 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
109112 filename : string ,
110113 options ?: GridFSBucketWriteStreamOptions
111114 ) : GridFSBucketWriteStream {
112- return new GridFSBucketWriteStream ( this , filename , options ) ;
115+ return new GridFSBucketWriteStream ( this , filename , {
116+ timeoutMS : this . s . options . timeoutMS ,
117+ ...options
118+ } ) ;
113119 }
114120
115121 /**
@@ -122,7 +128,11 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
122128 filename : string ,
123129 options ?: GridFSBucketWriteStreamOptions
124130 ) : GridFSBucketWriteStream {
125- return new GridFSBucketWriteStream ( this , filename , { ...options , id } ) ;
131+ return new GridFSBucketWriteStream ( this , filename , {
132+ timeoutMS : this . s . options . timeoutMS ,
133+ ...options ,
134+ id
135+ } ) ;
126136 }
127137
128138 /** Returns a readable stream (GridFSBucketReadStream) for streaming file data from GridFS. */
@@ -135,7 +145,7 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
135145 this . s . _filesCollection ,
136146 this . s . options . readPreference ,
137147 { _id : id } ,
138- options
148+ { timeoutMS : this . s . options . timeoutMS , ... options }
139149 ) ;
140150 }
141151
@@ -144,11 +154,27 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
144154 *
145155 * @param id - The id of the file doc
146156 */
147- async delete ( id : ObjectId ) : Promise < void > {
148- const { deletedCount } = await this . s . _filesCollection . deleteOne ( { _id : id } ) ;
157+ async delete ( id : ObjectId , options ?: { timeoutMS : number } ) : Promise < void > {
158+ const { timeoutMS } = resolveOptions ( this . s . db , options ) ;
159+ let timeoutContext : CSOTTimeoutContext | undefined = undefined ;
160+
161+ if ( timeoutMS ) {
162+ timeoutContext = new CSOTTimeoutContext ( {
163+ timeoutMS,
164+ serverSelectionTimeoutMS : this . s . db . client . options . serverSelectionTimeoutMS
165+ } ) ;
166+ }
149167
168+ const { deletedCount } = await this . s . _filesCollection . deleteOne (
169+ { _id : id } ,
170+ { timeoutMS : timeoutContext ?. remainingTimeMS }
171+ ) ;
172+
173+ const remainingTimeMS = timeoutContext ?. remainingTimeMS ;
174+ if ( remainingTimeMS != null && remainingTimeMS <= 0 )
175+ throw new MongoOperationTimeoutError ( `Timed out after ${ timeoutMS } ms` ) ;
150176 // Delete orphaned chunks before returning FileNotFound
151- await this . s . _chunksCollection . deleteMany ( { files_id : id } ) ;
177+ await this . s . _chunksCollection . deleteMany ( { files_id : id } , { timeoutMS : remainingTimeMS } ) ;
152178
153179 if ( deletedCount === 0 ) {
154180 // TODO(NODE-3483): Replace with more appropriate error
@@ -188,7 +214,7 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
188214 this . s . _filesCollection ,
189215 this . s . options . readPreference ,
190216 { filename } ,
191- { ...options , sort, skip }
217+ { timeoutMS : this . s . options . timeoutMS , ...options , sort, skip }
192218 ) ;
193219 }
194220
@@ -198,18 +224,36 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
198224 * @param id - the id of the file to rename
199225 * @param filename - new name for the file
200226 */
201- async rename ( id : ObjectId , filename : string ) : Promise < void > {
227+ async rename ( id : ObjectId , filename : string , options ?: { timeoutMS : number } ) : Promise < void > {
202228 const filter = { _id : id } ;
203229 const update = { $set : { filename } } ;
204- const { matchedCount } = await this . s . _filesCollection . updateOne ( filter , update ) ;
230+ const { matchedCount } = await this . s . _filesCollection . updateOne ( filter , update , options ) ;
205231 if ( matchedCount === 0 ) {
206232 throw new MongoRuntimeError ( `File with id ${ id } not found` ) ;
207233 }
208234 }
209235
210236 /** 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 ( ) ;
237+ async drop ( options ?: { timeoutMS : number } ) : Promise < void > {
238+ const { timeoutMS } = resolveOptions ( this . s . db , options ) ;
239+ let timeoutContext : CSOTTimeoutContext | undefined = undefined ;
240+
241+ if ( timeoutMS ) {
242+ timeoutContext = new CSOTTimeoutContext ( {
243+ timeoutMS,
244+ serverSelectionTimeoutMS : this . s . db . client . options . serverSelectionTimeoutMS
245+ } ) ;
246+ }
247+
248+ if ( timeoutContext ) {
249+ await this . s . _filesCollection . drop ( { timeoutMS : timeoutContext . remainingTimeMS } ) ;
250+ const remainingTimeMS = timeoutContext . getRemainingTimeMSOrThrow (
251+ `Timed out after ${ timeoutMS } ms`
252+ ) ;
253+ await this . s . _chunksCollection . drop ( { timeoutMS : remainingTimeMS } ) ;
254+ } else {
255+ await this . s . _filesCollection . drop ( ) ;
256+ await this . s . _chunksCollection . drop ( ) ;
257+ }
214258 }
215259}
0 commit comments