Skip to content

Commit 60bf5f9

Browse files
authored
[MongoDB Replication] Fix resumeTokens going back in time on busy change streams (#301)
* Add check for resumeTokens going back in time. * Reduce retry delay on general MongoDB change stream errors. * Add changeset.
1 parent a60f2c7 commit 60bf5f9

File tree

3 files changed

+19
-1
lines changed

3 files changed

+19
-1
lines changed

.changeset/sweet-years-tickle.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@powersync/service-module-mongodb': patch
3+
'@powersync/lib-service-mongodb': patch
4+
'@powersync/service-core': patch
5+
'@powersync/service-image': patch
6+
---
7+
8+
[MongoDB Replication] Fix resumeTokens going back in time on busy change streams.

modules/module-mongodb/src/replication/ChangeStream.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,16 @@ export class ChangeStream {
947947
timestamp: changeDocument.clusterTime!,
948948
resume_token: changeDocument._id
949949
});
950+
if (batch.lastCheckpointLsn != null && lsn < batch.lastCheckpointLsn) {
951+
// Checkpoint out of order - should never happen with MongoDB.
952+
// If it does happen, we throw an error to stop the replication - restarting should recover.
953+
// Since we use batch.lastCheckpointLsn for the next resumeAfter, this should not result in an infinite loop.
954+
// This is a workaround for the issue below, but we can keep this as a safety-check even if the issue is fixed.
955+
// Driver issue report: https://jira.mongodb.org/browse/NODE-7042
956+
throw new ReplicationAssertionError(
957+
`Change resumeToken ${(changeDocument._id as any)._data} (${timestampToDate(changeDocument.clusterTime!).toISOString()}) is less than last checkpoint LSN ${batch.lastCheckpointLsn}. Restarting replication.`
958+
);
959+
}
950960

951961
if (waitForCheckpointLsn != null && lsn >= waitForCheckpointLsn) {
952962
waitForCheckpointLsn = null;

modules/module-mongodb/src/replication/MongoErrorRateLimiter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export class MongoErrorRateLimiter implements ErrorRateLimiter {
2828
// Could be fail2ban or similar
2929
this.setDelay(120_000);
3030
} else {
31-
this.setDelay(30_000);
31+
this.setDelay(5_000);
3232
}
3333
}
3434

0 commit comments

Comments
 (0)