diff --git a/packages/db-mongodb/src/createVersion.ts b/packages/db-mongodb/src/createVersion.ts index 08902953ed9..7056eb09c59 100644 --- a/packages/db-mongodb/src/createVersion.ts +++ b/packages/db-mongodb/src/createVersion.ts @@ -79,6 +79,11 @@ export const createVersion: CreateVersion = async function createVersion( $eq: true, }, }, + { + createdAt: { + $lt: new Date(doc.createdAt), + }, + }, ], }, { $unset: { latest: 1 } }, diff --git a/packages/drizzle/src/createVersion.ts b/packages/drizzle/src/createVersion.ts index 4f41aa7aca7..2969489cd73 100644 --- a/packages/drizzle/src/createVersion.ts +++ b/packages/drizzle/src/createVersion.ts @@ -66,6 +66,7 @@ export async function createVersion( SET latest = false WHERE ${table.id} != ${result.id} AND ${table.parent} = ${parent} + AND ${table.createdAt} < ${result.createdAt} `, }) } diff --git a/test/versions/int.spec.ts b/test/versions/int.spec.ts index 6dbfed61981..6840c8d3f40 100644 --- a/test/versions/int.spec.ts +++ b/test/versions/int.spec.ts @@ -831,6 +831,61 @@ describe('Versions', () => { expect(docs.totalDocs).toStrictEqual(2) }) }) + + describe('Race conditions', () => { + it('should keep latest true with parallel writes', async () => { + const doc = await payload.create({ + collection: 'draft-posts', + data: { + description: 'A', + title: 'A', + }, + }) + + for (let i = 0; i < 200; i++) { + const writeAmount = 2 + + const promises = Array.from({ length: writeAmount }, async (_, i) => { + return new Promise((resolve) => { + // Add latency so updates aren't immediate after each other but still in parallel + setTimeout(() => { + payload + .update({ + id: doc.id, + collection: 'draft-posts', + data: {}, + draft: true, + }) + .then(resolve) + .catch(resolve) + }, i * 10) + }) + }) + + await Promise.all(promises) + + const { docs } = await payload.findVersions({ + collection: 'draft-posts', + where: { + and: [ + { + parent: { + equals: doc.id, + }, + }, + { + latest: { + equals: true, + }, + }, + ], + }, + }) + + expect(docs[0]).toBeDefined() + } + }) + }) }) describe('Querying', () => {