From 30b409a72acf8678322419e46f1af40bc81a44ee Mon Sep 17 00:00:00 2001 From: Reda Bourial Date: Tue, 27 Feb 2024 21:12:36 +0100 Subject: [PATCH 1/2] fixed race condition --- lib/publication.js | 7 ++++--- lib/publish_composite.js | 3 --- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/publication.js b/lib/publication.js index fc9e613..9f3fb2f 100644 --- a/lib/publication.js +++ b/lib/publication.js @@ -18,8 +18,6 @@ class Publication { this.childrenOptions = options.children || [] this.publishedDocs = new PublishedDocumentList() this.collectionName = options.collectionName - // property to store promises for added callbacks - this.addedPromises = [] } async publish () { @@ -27,6 +25,7 @@ class Publication { if (!this.cursor) { return } const collectionName = this._getCollectionName() + const promises = [] // Use Meteor.bindEnvironment to make sure the callbacks are run with the same // environmentVariables as when publishing the "parent". @@ -41,7 +40,7 @@ class Publication { }) // store the promise - this.addedPromises.push(addedPromise) + promises.push(addedPromise) }), changed: Meteor.bindEnvironment((newDoc, oldDoc) => { debugLog('Publication.observeHandle.changed', `${collectionName}:${newDoc._id}`) @@ -56,6 +55,8 @@ class Publication { this._removeDoc(collectionName, doc._id) } }) + // await the promises + await Promise.all(promises) } unpublish () { diff --git a/lib/publish_composite.js b/lib/publish_composite.js index 8bd74b9..1188200 100644 --- a/lib/publish_composite.js +++ b/lib/publish_composite.js @@ -20,9 +20,6 @@ function publishComposite (name, options) { publications.forEach(pub => pub.unpublish()) }) - // wait for all publications to finish processing initial added callbacks - await Promise.all(publications.flatMap(pub => pub.addedPromises)) - debugLog('Meteor.publish', 'ready') this.ready() }) From b8de4d0883bb46a1796a6edb7ebf8ce4ff921f93 Mon Sep 17 00:00:00 2001 From: Reda Bourial Date: Wed, 28 Feb 2024 08:35:24 +0100 Subject: [PATCH 2/2] optimized code --- lib/publication.js | 13 +++++++++---- lib/publish_composite.js | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/publication.js b/lib/publication.js index 9f3fb2f..bf02a95 100644 --- a/lib/publication.js +++ b/lib/publication.js @@ -18,6 +18,8 @@ class Publication { this.childrenOptions = options.children || [] this.publishedDocs = new PublishedDocumentList() this.collectionName = options.collectionName + this.promises = [] + this.childrenPublication = [] } async publish () { @@ -25,7 +27,6 @@ class Publication { if (!this.cursor) { return } const collectionName = this._getCollectionName() - const promises = [] // Use Meteor.bindEnvironment to make sure the callbacks are run with the same // environmentVariables as when publishing the "parent". @@ -40,7 +41,7 @@ class Publication { }) // store the promise - promises.push(addedPromise) + this.promises.push(addedPromise) }), changed: Meteor.bindEnvironment((newDoc, oldDoc) => { debugLog('Publication.observeHandle.changed', `${collectionName}:${newDoc._id}`) @@ -55,8 +56,6 @@ class Publication { this._removeDoc(collectionName, doc._id) } }) - // await the promises - await Promise.all(promises) } unpublish () { @@ -106,6 +105,7 @@ class Publication { : this.childrenOptions await Promise.all(children.map(async (options) => { const pub = new Publication(this.subscription, options, [doc].concat(this.args)) + this.childrenPublication.push(pub) this.publishedDocs.addChildPub(doc._id, pub) await pub.publish() })) @@ -170,6 +170,11 @@ class Publication { publication.unpublish() }) } + + async awaitPromises () { + await Promise.all(this.promises) + await Promise.all(this.childrenPublication.map(p => p.awaitPromises())) + } } export default Publication diff --git a/lib/publish_composite.js b/lib/publish_composite.js index 1188200..46f095a 100644 --- a/lib/publish_composite.js +++ b/lib/publish_composite.js @@ -20,6 +20,7 @@ function publishComposite (name, options) { publications.forEach(pub => pub.unpublish()) }) + await Promise.all(publications.map(p => p.awaitPromises())) debugLog('Meteor.publish', 'ready') this.ready() })