PubSub across DDP connections

Hey everyone!

I’ve got a collection on server1 and I want to publish it’s count to server2. I have been successful in getting documents from server1 to server2 as follows:

//server1
EmailCampaigns = new Mongo.Collection('emailCampaigns');
Meteor.publish("emailCampaigns", ()=>{return EmailCampaigns.find()})

//server2
emailConn = DDP.connect(Meteor.settings.public.emailUrl);
EmailCampaigns = new Mongo.Collection('emailCampaigns', {connection:emailConn);

I can publish from server1 to server2 with no issues as follows:

emailConn.subscribe("emailCampaigns");

All of this works as expected but I have a problem when I want to do anything inside the publication with this.

When I call

//server2
emailConn.subscribe("messageCount", {});`

The following publication breaks:

//server1
Meteor.publish("messageCount", (query) =>{
  const self = this;
  check(query, Object);
  let count = 0;
  let initializing = true;

  let handle = EmailCampaigns.find(query).observeChanges({
    added: function (id) {
      count++;
      if (!initializing)
        self.changed("counts", roomId, {count: count});
    },
    removed: function (id) {
      count--;
      self.changed("counts", roomId, {count: count});
    }
  });

  initializing = false;
  self.added("counts", query, {count: count});
  self.ready();
  self.onStop(function () {
    handle.stop();
  });
})

And I get the following Error:

Exception from sub messageCount id JdQHxRgpS7RKcJS8X TypeError: Object [object global] has no method 'added'

When subscribing to a publication on a different meteor server this isn’t the same as this when subscribing on the same server.

Maybe I’m doing something wrong? I haven’t been able to figure this out yet though and i was wondering if anyone has had a similar problem.

Ok, so I figured out the problem. Using Meteor.publish("somePub", ()=>{return Cursor.find()}) returns the Meteor object but using Meteor.publish("somePub", function(){return Cursor.find()}) works as expected. @sashko is this expected behavior? I found a related SO post.

this has to do with how this is assigned in Meteor.publish functions. using an arrow function changes the expected value of this inside that function which means you get a reference to the server’s “global” this instead of the publish function’s this.

does this make sense? :wink:

derick bailey has a great free email course on “mastering this” that will really help understanding all of that stuff.

3 Likes

Just to add - Kyle Simpson’s You Don’t Know JS: this & Object Prototypes book (free via GitHub and/or buy it via O’Reilly) is awesome for “this” (pun intended) as well.

Yes, that is expected, MDG has not made their publish and method functions be ES2015 friendly yet, you need to keep using functions on publications and methods for now.

1 Like

I don’t think it’s so much being “ES2015 friendly” as it is just using the right function definition. Arrow functions aren’t a direct replacement for functions, they’re a new tool with different functionality for different use cases. They don’t create a new lexical scope for that function. The right way for methods and pubs would just to use the regular function definition. I suppose they could pass in a “context” object into your publish callback as an argument, but that’s essentially the same as calling your callback with .apply() and passing in the “this” arg like they do right now, and it would break backwards compatibility

1 Like