@@ -87,7 +87,8 @@ func (c *MongoConnector) SetupReplication(ctx context.Context, input *protos.Set
8787 if err != nil {
8888 return model.SetupReplicationResult {}, fmt .Errorf ("failed to create changestream pipeline: %w" , err )
8989 }
90- changeStream , err := c .client .Watch (ctx , pipeline , changeStreamOpts )
90+
91+ changeStream , err := createChangeStream (c .client , ctx , pipeline , changeStreamOpts )
9192 if err != nil {
9293 return model.SetupReplicationResult {}, fmt .Errorf ("failed to start change stream for storing initial resume token: %w" , err )
9394 }
@@ -156,7 +157,7 @@ func (c *MongoConnector) PullRecords(
156157 return err
157158 }
158159
159- changeStream , err := c .client . Watch ( ctx , pipeline , changeStreamOpts )
160+ changeStream , err := createChangeStream ( c .client , ctx , pipeline , changeStreamOpts )
160161 if err != nil {
161162 if isResumeTokenNotFoundError (err ) && resumeToken != nil {
162163 timestamp , err := decodeTimestampFromResumeToken (resumeToken )
@@ -165,7 +166,7 @@ func (c *MongoConnector) PullRecords(
165166 }
166167 changeStreamOpts .SetStartAtOperationTime (& timestamp )
167168 changeStreamOpts .SetResumeAfter (nil )
168- changeStream , err = c .client . Watch ( ctx , pipeline , changeStreamOpts )
169+ changeStream , err = createChangeStream ( c .client , ctx , pipeline , changeStreamOpts )
169170 if err != nil {
170171 return fmt .Errorf ("failed to recreate change stream: %w" , err )
171172 }
@@ -299,7 +300,7 @@ func (c *MongoConnector) PullRecords(
299300 changeStreamOpts .SetStartAtOperationTime (nil )
300301 }
301302
302- changeStream , err = c .client . Watch ( ctx , pipeline , changeStreamOpts )
303+ changeStream , err = createChangeStream ( c .client , ctx , pipeline , changeStreamOpts )
303304 if err != nil {
304305 return err
305306 }
@@ -461,6 +462,16 @@ func createPipeline(tableNameMapping map[string]model.NameAndExclude) (mongo.Pip
461462 return pipeline , nil
462463}
463464
465+ // createChangeStream calls client.Watch with a 5 minute context deadline
466+ // so the driver sends it as maxTimeMS over the wire. Otherwise server-
467+ // side default maxTimeMS is used which can sometimes be too short.
468+ func createChangeStream (client * mongo.Client , parent context.Context , pipeline mongo.Pipeline , opts * options.ChangeStreamOptionsBuilder ,
469+ ) (* mongo.ChangeStream , error ) {
470+ watchCtx , cancel := context .WithTimeout (parent , 5 * time .Minute )
471+ defer cancel ()
472+ return client .Watch (watchCtx , pipeline , opts )
473+ }
474+
464475// This can happen if the resumeToken we are attempting to `ResumeAfter` refers to a table that has been
465476// filtered out of the change stream pipeline (for example, if a user pauses and edits a mirror). If
466477// this happens, we decode the resumeToken and extract its operation time, and start a new changeStream
0 commit comments