From c76a1414312be5d77567fcb8dde7b9907249375b Mon Sep 17 00:00:00 2001 From: Quentin Hello <9997584+qhello@users.noreply.github.com> Date: Tue, 20 May 2025 16:03:56 +0200 Subject: [PATCH 1/9] fix(NODE-6955): add missing wallTime property to ChangeStreamDocumentCommon --- src/change_stream.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/change_stream.ts b/src/change_stream.ts index 403c464edd..1db52eb617 100644 --- a/src/change_stream.ts +++ b/src/change_stream.ts @@ -183,6 +183,14 @@ export interface ChangeStreamDocumentCommon { */ clusterTime?: Timestamp; + /** + * The server date and time of the database operation. + * wallTime differs from clusterTime in that clusterTime is a timestamp taken from the oplog entry associated with the database operation event. + * The format is "YYYY-MM-DD HH:MM.SS.millis". + */ + wallTime?: string; + + /** * The transaction number. * Only present if the operation is part of a multi-document transaction. From a538b3bfe6c734c5cb12f2d08fe1424ac0457e07 Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 27 May 2025 14:44:40 +0100 Subject: [PATCH 2/9] chore: fix lint --- src/change_stream.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/change_stream.ts b/src/change_stream.ts index 1db52eb617..b4136edd4a 100644 --- a/src/change_stream.ts +++ b/src/change_stream.ts @@ -184,13 +184,12 @@ export interface ChangeStreamDocumentCommon { clusterTime?: Timestamp; /** - * The server date and time of the database operation. + * The server date and time of the database operation. * wallTime differs from clusterTime in that clusterTime is a timestamp taken from the oplog entry associated with the database operation event. * The format is "YYYY-MM-DD HH:MM.SS.millis". */ wallTime?: string; - /** * The transaction number. * Only present if the operation is part of a multi-document transaction. From 3f6853e94240aea4954c187e07b148e98ae5629c Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 27 May 2025 14:46:38 +0100 Subject: [PATCH 3/9] test: add type test --- test/types/change_stream.test-d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/types/change_stream.test-d.ts b/test/types/change_stream.test-d.ts index 02815cefd6..c61fde533b 100644 --- a/test/types/change_stream.test-d.ts +++ b/test/types/change_stream.test-d.ts @@ -63,6 +63,7 @@ expectType(change._id); expectType(change.clusterTime); expectType(change.txnNumber); // Could be a Long if promoteLongs is off expectType(change.lsid); +expectType(change.wallTime); type CrudChangeDoc = | ChangeStreamInsertDocument // C From 3cde59be1505f3c4878b22612f1ef1d1edf93b6b Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 27 May 2025 20:46:41 +0100 Subject: [PATCH 4/9] test: add wallTime tests --- src/change_stream.ts | 1 + test/integration/change-streams/change_stream.test.ts | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/change_stream.ts b/src/change_stream.ts index b4136edd4a..c38024172b 100644 --- a/src/change_stream.ts +++ b/src/change_stream.ts @@ -187,6 +187,7 @@ export interface ChangeStreamDocumentCommon { * The server date and time of the database operation. * wallTime differs from clusterTime in that clusterTime is a timestamp taken from the oplog entry associated with the database operation event. * The format is "YYYY-MM-DD HH:MM.SS.millis". + * @sinceServerVersion 6.0.0 */ wallTime?: string; diff --git a/test/integration/change-streams/change_stream.test.ts b/test/integration/change-streams/change_stream.test.ts index 7a188b2e33..d4ce3d8099 100644 --- a/test/integration/change-streams/change_stream.test.ts +++ b/test/integration/change-streams/change_stream.test.ts @@ -1259,7 +1259,8 @@ describe('Change Streams', function () { // Running on replicaset because other topologies are finiky with the cluster-wide events // Dropping and renaming and creating collections in order to achieve a clean slate isn't worth the goal of these tests // We just want to show that the new ChangeStreamDocument type information can reproduced in a real env - topologies: ['replicaset'] + topologies: ['replicaset'], + minServerVersion: '6.0' }) .createEntities([ { client: { id: 'client0' } }, @@ -1325,6 +1326,7 @@ describe('Change Streams', function () { operationType: 'drop', ns: { db: 'dbToDrop', coll: 'collInDbToDrop' }, clusterTime: { $$type: 'timestamp' }, + wallTime: { $$type: 'date' }, txnNumber: { $$exists: false }, lsid: { $$exists: false } } @@ -1337,6 +1339,7 @@ describe('Change Streams', function () { operationType: 'dropDatabase', ns: { db: 'dbToDrop', coll: { $$exists: false } }, clusterTime: { $$type: 'timestamp' }, + wallTime: { $$type: 'date' }, txnNumber: { $$exists: false }, lsid: { $$exists: false } } @@ -1349,6 +1352,7 @@ describe('Change Streams', function () { operationType: 'drop', ns: { db: 'dbToDrop', coll: 'collInDbToDrop' }, clusterTime: { $$type: 'timestamp' }, + wallTime: { $$type: 'date' }, txnNumber: { $$exists: false }, lsid: { $$exists: false } } @@ -1360,6 +1364,7 @@ describe('Change Streams', function () { _id: { $$exists: true }, operationType: 'invalidate', clusterTime: { $$type: 'timestamp' }, + wallTime: { $$type: 'date' }, txnNumber: { $$exists: false }, lsid: { $$exists: false } } @@ -1420,6 +1425,7 @@ describe('Change Streams', function () { documentKey: { _id: 3 }, ns: { db: 'changeStreamDocShape', coll: 'collection0' }, clusterTime: { $$type: 'timestamp' }, + wallTime: { $$type: 'date' }, txnNumber: { $$type: ['long', 'int'] }, lsid: { $$sessionLsid: 'session0' } } @@ -1472,6 +1478,7 @@ describe('Change Streams', function () { documentKey: { _id: 3 }, ns: { db: 'renameDb', coll: 'collToRename' }, clusterTime: { $$type: 'timestamp' }, + wallTime: { $$type: 'date' }, txnNumber: { $$exists: false }, lsid: { $$exists: false } } @@ -1497,6 +1504,7 @@ describe('Change Streams', function () { ns: { db: 'renameDb', coll: 'collToRename' }, to: { db: 'renameDb', coll: 'newCollectionName' }, clusterTime: { $$type: 'timestamp' }, + wallTime: { $$type: 'date' }, txnNumber: { $$exists: false }, lsid: { $$exists: false } } From 35bb5447ed8150196256ab34b235d0737b4b9dce Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 27 May 2025 21:35:26 +0100 Subject: [PATCH 5/9] fix: type --- src/change_stream.ts | 2 +- test/types/change_stream.test-d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/change_stream.ts b/src/change_stream.ts index c38024172b..9248a5da6e 100644 --- a/src/change_stream.ts +++ b/src/change_stream.ts @@ -189,7 +189,7 @@ export interface ChangeStreamDocumentCommon { * The format is "YYYY-MM-DD HH:MM.SS.millis". * @sinceServerVersion 6.0.0 */ - wallTime?: string; + wallTime?: Date; /** * The transaction number. diff --git a/test/types/change_stream.test-d.ts b/test/types/change_stream.test-d.ts index c61fde533b..f4a398f7c6 100644 --- a/test/types/change_stream.test-d.ts +++ b/test/types/change_stream.test-d.ts @@ -63,7 +63,7 @@ expectType(change._id); expectType(change.clusterTime); expectType(change.txnNumber); // Could be a Long if promoteLongs is off expectType(change.lsid); -expectType(change.wallTime); +expectType(change.wallTime); type CrudChangeDoc = | ChangeStreamInsertDocument // C From 40ebaa78299e32ce77128accb3579c1b8cb4a6ba Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 27 May 2025 21:35:26 +0100 Subject: [PATCH 6/9] fix: type --- .../change-streams/change_stream.test.ts | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/test/integration/change-streams/change_stream.test.ts b/test/integration/change-streams/change_stream.test.ts index d4ce3d8099..8575913c2f 100644 --- a/test/integration/change-streams/change_stream.test.ts +++ b/test/integration/change-streams/change_stream.test.ts @@ -170,6 +170,26 @@ describe('Change Streams', function () { } }); + it('contains a wallType date property on the change', { + metadata: { requires: { topology: 'replicaset', mongodb: '>=6.0.0' } }, + async test() { + const collection = db.collection('wallTimeTest'); + const changeStream = collection.watch(pipeline); + + const willBeChanges = on(changeStream, 'change'); + await once(changeStream.cursor, 'init'); + + await collection.insertOne({ d: 4 }); + + const change = (await willBeChanges.next()).value[0]; + + await changeStream.close(); + + expect(change).to.have.property('wallTime'); + expect(change.wallType).to.be.instanceOf(Date); + } + }); + it('should create a ChangeStream on a collection and emit change events', { metadata: { requires: { topology: 'replicaset' } }, async test() { @@ -1259,8 +1279,7 @@ describe('Change Streams', function () { // Running on replicaset because other topologies are finiky with the cluster-wide events // Dropping and renaming and creating collections in order to achieve a clean slate isn't worth the goal of these tests // We just want to show that the new ChangeStreamDocument type information can reproduced in a real env - topologies: ['replicaset'], - minServerVersion: '6.0' + topologies: ['replicaset'] }) .createEntities([ { client: { id: 'client0' } }, @@ -1326,7 +1345,6 @@ describe('Change Streams', function () { operationType: 'drop', ns: { db: 'dbToDrop', coll: 'collInDbToDrop' }, clusterTime: { $$type: 'timestamp' }, - wallTime: { $$type: 'date' }, txnNumber: { $$exists: false }, lsid: { $$exists: false } } @@ -1339,7 +1357,6 @@ describe('Change Streams', function () { operationType: 'dropDatabase', ns: { db: 'dbToDrop', coll: { $$exists: false } }, clusterTime: { $$type: 'timestamp' }, - wallTime: { $$type: 'date' }, txnNumber: { $$exists: false }, lsid: { $$exists: false } } @@ -1352,7 +1369,6 @@ describe('Change Streams', function () { operationType: 'drop', ns: { db: 'dbToDrop', coll: 'collInDbToDrop' }, clusterTime: { $$type: 'timestamp' }, - wallTime: { $$type: 'date' }, txnNumber: { $$exists: false }, lsid: { $$exists: false } } @@ -1364,7 +1380,6 @@ describe('Change Streams', function () { _id: { $$exists: true }, operationType: 'invalidate', clusterTime: { $$type: 'timestamp' }, - wallTime: { $$type: 'date' }, txnNumber: { $$exists: false }, lsid: { $$exists: false } } @@ -1425,7 +1440,6 @@ describe('Change Streams', function () { documentKey: { _id: 3 }, ns: { db: 'changeStreamDocShape', coll: 'collection0' }, clusterTime: { $$type: 'timestamp' }, - wallTime: { $$type: 'date' }, txnNumber: { $$type: ['long', 'int'] }, lsid: { $$sessionLsid: 'session0' } } @@ -1478,7 +1492,6 @@ describe('Change Streams', function () { documentKey: { _id: 3 }, ns: { db: 'renameDb', coll: 'collToRename' }, clusterTime: { $$type: 'timestamp' }, - wallTime: { $$type: 'date' }, txnNumber: { $$exists: false }, lsid: { $$exists: false } } @@ -1504,7 +1517,6 @@ describe('Change Streams', function () { ns: { db: 'renameDb', coll: 'collToRename' }, to: { db: 'renameDb', coll: 'newCollectionName' }, clusterTime: { $$type: 'timestamp' }, - wallTime: { $$type: 'date' }, txnNumber: { $$exists: false }, lsid: { $$exists: false } } From e296045ee2fcbc2f4665d6888b3e49a7e0b2a1cc Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Wed, 28 May 2025 10:31:15 +0100 Subject: [PATCH 7/9] test: fix check --- test/integration/change-streams/change_stream.test.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/integration/change-streams/change_stream.test.ts b/test/integration/change-streams/change_stream.test.ts index 8575913c2f..aaa7f7c889 100644 --- a/test/integration/change-streams/change_stream.test.ts +++ b/test/integration/change-streams/change_stream.test.ts @@ -170,7 +170,7 @@ describe('Change Streams', function () { } }); - it('contains a wallType date property on the change', { + it('contains a wallTtime date property on the change', { metadata: { requires: { topology: 'replicaset', mongodb: '>=6.0.0' } }, async test() { const collection = db.collection('wallTimeTest'); @@ -186,7 +186,10 @@ describe('Change Streams', function () { await changeStream.close(); expect(change).to.have.property('wallTime'); - expect(change.wallType).to.be.instanceOf(Date); + // For cases where it's not undefined we check it's a Date. + if (change.wallTime) { + expect(change.wallType).to.be.instanceOf(Date); + } } }); From 1530f4c3a6681cef27a66b0a60cf55195756053a Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Wed, 28 May 2025 18:06:52 +0100 Subject: [PATCH 8/9] test: fix test assertion --- test/integration/change-streams/change_stream.test.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/integration/change-streams/change_stream.test.ts b/test/integration/change-streams/change_stream.test.ts index aaa7f7c889..1e9ac09901 100644 --- a/test/integration/change-streams/change_stream.test.ts +++ b/test/integration/change-streams/change_stream.test.ts @@ -170,7 +170,7 @@ describe('Change Streams', function () { } }); - it('contains a wallTtime date property on the change', { + it('contains a wallTime date property on the change', { metadata: { requires: { topology: 'replicaset', mongodb: '>=6.0.0' } }, async test() { const collection = db.collection('wallTimeTest'); @@ -186,10 +186,7 @@ describe('Change Streams', function () { await changeStream.close(); expect(change).to.have.property('wallTime'); - // For cases where it's not undefined we check it's a Date. - if (change.wallTime) { - expect(change.wallType).to.be.instanceOf(Date); - } + expect(change.wallTime).to.be.instanceOf(Date); } }); From ceb4f60903bae619c7044af2482aa552a52ff433 Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Mon, 2 Jun 2025 13:12:46 -0400 Subject: [PATCH 9/9] fix: walltime only where included --- src/change_stream.ts | 59 ++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/src/change_stream.ts b/src/change_stream.ts index 9248a5da6e..ed847519e8 100644 --- a/src/change_stream.ts +++ b/src/change_stream.ts @@ -183,14 +183,6 @@ export interface ChangeStreamDocumentCommon { */ clusterTime?: Timestamp; - /** - * The server date and time of the database operation. - * wallTime differs from clusterTime in that clusterTime is a timestamp taken from the oplog entry associated with the database operation event. - * The format is "YYYY-MM-DD HH:MM.SS.millis". - * @sinceServerVersion 6.0.0 - */ - wallTime?: Date; - /** * The transaction number. * Only present if the operation is part of a multi-document transaction. @@ -213,6 +205,16 @@ export interface ChangeStreamDocumentCommon { splitEvent?: ChangeStreamSplitEvent; } +/** @public */ +export interface ChangeStreamDocumentWallTime { + /** + * The server date and time of the database operation. + * wallTime differs from clusterTime in that clusterTime is a timestamp taken from the oplog entry associated with the database operation event. + * @sinceServerVersion 6.0.0 + */ + wallTime?: Date; +} + /** @public */ export interface ChangeStreamDocumentCollectionUUID { /** @@ -247,7 +249,8 @@ export interface ChangeStreamDocumentOperationDescription { export interface ChangeStreamInsertDocument extends ChangeStreamDocumentCommon, ChangeStreamDocumentKey, - ChangeStreamDocumentCollectionUUID { + ChangeStreamDocumentCollectionUUID, + ChangeStreamDocumentWallTime { /** Describes the type of operation represented in this change notification */ operationType: 'insert'; /** This key will contain the document being inserted */ @@ -263,7 +266,8 @@ export interface ChangeStreamInsertDocument export interface ChangeStreamUpdateDocument extends ChangeStreamDocumentCommon, ChangeStreamDocumentKey, - ChangeStreamDocumentCollectionUUID { + ChangeStreamDocumentCollectionUUID, + ChangeStreamDocumentWallTime { /** Describes the type of operation represented in this change notification */ operationType: 'update'; /** @@ -293,7 +297,8 @@ export interface ChangeStreamUpdateDocument */ export interface ChangeStreamReplaceDocument extends ChangeStreamDocumentCommon, - ChangeStreamDocumentKey { + ChangeStreamDocumentKey, + ChangeStreamDocumentWallTime { /** Describes the type of operation represented in this change notification */ operationType: 'replace'; /** The fullDocument of a replace event represents the document after the insert of the replacement document */ @@ -317,7 +322,8 @@ export interface ChangeStreamReplaceDocument extends ChangeStreamDocumentCommon, ChangeStreamDocumentKey, - ChangeStreamDocumentCollectionUUID { + ChangeStreamDocumentCollectionUUID, + ChangeStreamDocumentWallTime { /** Describes the type of operation represented in this change notification */ operationType: 'delete'; /** Namespace the delete event occurred on */ @@ -338,7 +344,8 @@ export interface ChangeStreamDeleteDocument */ export interface ChangeStreamDropDocument extends ChangeStreamDocumentCommon, - ChangeStreamDocumentCollectionUUID { + ChangeStreamDocumentCollectionUUID, + ChangeStreamDocumentWallTime { /** Describes the type of operation represented in this change notification */ operationType: 'drop'; /** Namespace the drop event occurred on */ @@ -351,7 +358,8 @@ export interface ChangeStreamDropDocument */ export interface ChangeStreamRenameDocument extends ChangeStreamDocumentCommon, - ChangeStreamDocumentCollectionUUID { + ChangeStreamDocumentCollectionUUID, + ChangeStreamDocumentWallTime { /** Describes the type of operation represented in this change notification */ operationType: 'rename'; /** The new name for the `ns.coll` collection */ @@ -364,7 +372,9 @@ export interface ChangeStreamRenameDocument * @public * @see https://www.mongodb.com/docs/manual/reference/change-events/#dropdatabase-event */ -export interface ChangeStreamDropDatabaseDocument extends ChangeStreamDocumentCommon { +export interface ChangeStreamDropDatabaseDocument + extends ChangeStreamDocumentCommon, + ChangeStreamDocumentWallTime { /** Describes the type of operation represented in this change notification */ operationType: 'dropDatabase'; /** The database dropped */ @@ -375,7 +385,9 @@ export interface ChangeStreamDropDatabaseDocument extends ChangeStreamDocumentCo * @public * @see https://www.mongodb.com/docs/manual/reference/change-events/#invalidate-event */ -export interface ChangeStreamInvalidateDocument extends ChangeStreamDocumentCommon { +export interface ChangeStreamInvalidateDocument + extends ChangeStreamDocumentCommon, + ChangeStreamDocumentWallTime { /** Describes the type of operation represented in this change notification */ operationType: 'invalidate'; } @@ -388,7 +400,8 @@ export interface ChangeStreamInvalidateDocument extends ChangeStreamDocumentComm export interface ChangeStreamCreateIndexDocument extends ChangeStreamDocumentCommon, ChangeStreamDocumentCollectionUUID, - ChangeStreamDocumentOperationDescription { + ChangeStreamDocumentOperationDescription, + ChangeStreamDocumentWallTime { /** Describes the type of operation represented in this change notification */ operationType: 'createIndexes'; } @@ -401,7 +414,8 @@ export interface ChangeStreamCreateIndexDocument export interface ChangeStreamDropIndexDocument extends ChangeStreamDocumentCommon, ChangeStreamDocumentCollectionUUID, - ChangeStreamDocumentOperationDescription { + ChangeStreamDocumentOperationDescription, + ChangeStreamDocumentWallTime { /** Describes the type of operation represented in this change notification */ operationType: 'dropIndexes'; } @@ -413,7 +427,8 @@ export interface ChangeStreamDropIndexDocument */ export interface ChangeStreamCollModDocument extends ChangeStreamDocumentCommon, - ChangeStreamDocumentCollectionUUID { + ChangeStreamDocumentCollectionUUID, + ChangeStreamDocumentWallTime { /** Describes the type of operation represented in this change notification */ operationType: 'modify'; } @@ -424,7 +439,8 @@ export interface ChangeStreamCollModDocument */ export interface ChangeStreamCreateDocument extends ChangeStreamDocumentCommon, - ChangeStreamDocumentCollectionUUID { + ChangeStreamDocumentCollectionUUID, + ChangeStreamDocumentWallTime { /** Describes the type of operation represented in this change notification */ operationType: 'create'; @@ -443,7 +459,8 @@ export interface ChangeStreamCreateDocument export interface ChangeStreamShardCollectionDocument extends ChangeStreamDocumentCommon, ChangeStreamDocumentCollectionUUID, - ChangeStreamDocumentOperationDescription { + ChangeStreamDocumentOperationDescription, + ChangeStreamDocumentWallTime { /** Describes the type of operation represented in this change notification */ operationType: 'shardCollection'; }