meteor-publish-composite
                                
                                
                                
                                    meteor-publish-composite copied to clipboard
                            
                            
                            
                        Parent is not always changed when updating a grand parent and a parent of a child
If I have a meteor-publish-composite having a grand parent, a parent and a child and I do a mongo update to the grand parent and the parent., the parent is not always updated on the client. ex.
Meteor.publishComposite("parentsAndChilds", filterByUser => ({
  find() {
    return Parents.find();
  },
  children: [
    {
      find(parent) {
        return Childs.find({ _id: { $in: parent.childs } });
      },
      children: [
        {
          find(child) {
            //fake a sub children that take time to load
            Meteor._sleepForMs(100);
            return Childs.find({ _id: { $in: [] } });
          }
        }
      ]
    }
  ]
}));
Meteor.methods({
  updateRandomString(childId) {
    Parents.update(
      { childs: childId },
      { $set: { name: Random.id() } },
      { multi: true }
    );
    Meteor._sleepForMs(50);
    Childs.update({ _id: childId }, { $set: { name: Random.id() } });
  }
});
the problem happen in publication.js
        this.observeHandle = this.cursor.observe({
            added: Meteor.bindEnvironment((doc) => {
                const alreadyPublished = this.publishedDocs.has(doc._id);
                if (alreadyPublished) {
                    debugLog('Publication.observeHandle.added', `${collectionName}:${doc._id} already published`);
                    this.publishedDocs.unflagForRemoval(doc._id);
                    this._republishChildrenOf(doc);
                    this.subscription.changed(collectionName, doc._id, doc);
                } else {
                    this.publishedDocs.add(collectionName, doc._id);
                    this._publishChildrenOf(doc);
                    this.subscription.added(collectionName, doc);
                }
            }),
            changed: Meteor.bindEnvironment((newDoc) => {
                debugLog('Publication.observeHandle.changed', `${collectionName}:${newDoc._id}`);
                this._republishChildrenOf(newDoc);
            }),
            removed: (doc) => {
                debugLog('Publication.observeHandle.removed', `${collectionName}:${doc._id}`);
                this._removeDoc(collectionName, doc._id);
            },
        });
        this.observeChangesHandle = this.cursor.observeChanges({
            changed: (id, fields) => {
                debugLog('Publication.observeChangesHandle.changed', `${collectionName}:${id}`);
                this.subscription.changed(collectionName, id, fields);
            },
        });
In my example,
1 Parents.update is executed
2. _republishChildrenOf is called and the publish function of "Childs" is called
3. the code go through 'Publication.observeHandle.added', ...  already published and _republishChildrenOf of "Childs" is called.
4. this execute my code " //fake a sub children that take time to load"
5. during the sleep of 100 ms, the code after the sleep of 50ms is executed and  Childs.update is called
6. this would normally called the function  this.observeChangesHandle for the "Childs" subscription but, as the code in the function publish is still waiting for the " //fake a sub children that take time to load",  this.cursor.observeChanges is never called and Childs is never updated in the client.
Changing the order of this.observeHandle and this.observeChangesHandle in "publication.js" fixe the bug .
        this.observeChangesHandle = this.cursor.observeChanges({
            changed: (id, fields) => {
                debugLog('Publication.observeChangesHandle.changed', `${collectionName}:${id}`);
                this.subscription.changed(collectionName, id, fields);
            },
        });
        this.observeHandle = this.cursor.observe({
            added: Meteor.bindEnvironment((doc) => {
                const alreadyPublished = this.publishedDocs.has(doc._id);
                if (alreadyPublished) {
                    debugLog('Publication.observeHandle.added', `${collectionName}:${doc._id} already published`);
                    this.publishedDocs.unflagForRemoval(doc._id);
                    this._republishChildrenOf(doc);
                    this.subscription.changed(collectionName, doc._id, doc);
                } else {
                    this.publishedDocs.add(collectionName, doc._id);
                    this._publishChildrenOf(doc);
                    this.subscription.added(collectionName, doc);
                }
            }),
            changed: Meteor.bindEnvironment((newDoc) => {
                debugLog('Publication.observeHandle.changed', `${collectionName}:${newDoc._id}`);
                this._republishChildrenOf(newDoc);
            }),
            removed: (doc) => {
                debugLog('Publication.observeHandle.removed', `${collectionName}:${doc._id}`);
                this._removeDoc(collectionName, doc._id);
            },
        });
I have created a project to reproduce the bug.
git clone https://github.com/ericm546/bug-publish-composite.git
cd bug-publish-composite
npm install
meteor
Clicking on a button update the random name of the element and his parent, but only the parent is changed in the browser.
the important code is in /server/main.js