Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to undo "Meteor.publish", and undo "new Meteor.Collection"

I see that when publishing, the collection._connection.publish_handlers is populated, and so does the collection._connection.method_handlers, and probably other areas.

I want to basically cleanup the memory by removing the references to that collection and it's publication entirely.

Basically each user of the app has a list of collections for that user. There is a publish function that looks like this for the user to get their list of collections:

Meteor.publish('users_collections', function() {
  var self = this;
  var handle = UsersCollections.find({ownerId: self.userId}).observeChanges({
    added: function(id, collectionInfo) {
      UsersCollectionManager.addUsersCollection(self.userId, collectionInfo.name);
    }
  });
});

That publishes that user's list of collections (and any user that connects gets their list).

Once the user gets their list, each of those collections is made reactive with new Meteor.Collection and then published.

UsersCollectionManager.addUsersCollection = function(userId, collectionName) {
  if (self.collections[userId].collections[collectionName] === undefined) {
    self.collections[userId].collections[collectionName] = new Meteor.Collection(collectionName);

    Meteor.publish(collectionName, function() {
      return self.collections[userId].collections[collectionName].find();
    });
  }
};

Once the user disconnects I have a function that gets run.

if that user doesn't have any connections open (ex: if they had multiple windows open and all the connections are closed "all windows closed") then it starts a 30s timeout to:

  • cleanup all these publish calls and new Meteor.Collection calls" to save memory

As the other user's of the app won't need this user's collections.

I'm not sure how to actually cleanup those from memory.

I don't see a "unpublish" or "Collection.stop" type of methods in the Meteor API.

How would I perform cleanup?

like image 983
PleaseHelpMeFigureThisOut Avatar asked Mar 09 '14 18:03

PleaseHelpMeFigureThisOut


1 Answers

You need to do this in two steps. First, stop and delete the publications, then delete the collection from Meteor.

The first step is fairly easy. It requires you to store the handles of each subscription:

var handles = [];

Meteor.publish('some data', function() {
  //Do stuff, send cursors, this.ready(), ...
  handles.push(this);
});

And later in time, stop them:

var handle;
while(handle = handles.shift()) {
  handle.stop();
}

All your publications are stopped. Now to delete the publication handler. It's less standard :

delete Meteor.default_server.publish_handlers['some data'];
delete Meteor.server.publish_handlers['some data'];

You basically have to burn down the reference to the handler. That's why it's less standard.

For the collection you first need to remove all documents then you have to delete the reference. Fortunately deleting all documents is very easy:

someCollection.remove({}, {multi : true}); //kaboom

Deleting the reference to the collection is trickier. If it is a collection declared without a name (new Mongo.Collection(null);), then you can just delete the variable (delete someCollection), it is not stored anywhere else as far as I know.
If it is a named collection, then it exists in the Mongo database, which means you have to tell Mongo to drop it. I have no idea how to do that at the moment. Maybe the Mongo driver can do it, ot it will need some takeover on the DDP connection.

like image 106
Kyll Avatar answered Nov 13 '22 13:11

Kyll