Pub-Sub data without mongoDB is not working


#1

I’m trying to implement a basic chat messaging server without storing the messages in MongoDB.
This is just to test the functionality, how it works, Here is my implementation.

if(Meteor.isServer){
    export const Messages = new Meteor.Collection("messages", {connection: null});
}

//Publish function

if(Meteor.isServer){
  Meteor.publish('messages', function(rid = 'ankit') {
    let self, finder, finderHandle;
    if (!this.userId) {
      return this.ready();
    }
    
    check(rid, String);
    finderHandle = Messages.find({});

    //
    finderHandle.observe({
      added: function (id, fields) {
        this.added( 'messages' , id, fields )
      }, // Use either added() OR(!)  ()
      changed: function (id, fields) {
        this.changed( 'messages' , id)
      },
      removed: function (id){
        this.removed( 'messages' , id, fields )
      }
    });

    this.ready();
  });
}

sendMessage Method

if (Meteor.isServer) {
	Meteor.methods({
		sendMessage: function (message){
			check(message, {
				msg: String,
				rid: String
			});

			if (! this.userId) {
				throw new Meteor.Error('not-authorized');
			}

			let save = Messages.insert({
				msg: message.msg,
				rid: message.rid
			});

			console.log("message saved")
			console.log(message);
			return {
				success: true
			};
		}
	});
}

and on client-side, I’m trying receiving the update but nothing seems to come.

if(Meteor.isClient){
  let Messages = new Mongo.Collection('messages')

  var user = {username: 'anil'};

  Meteor.loginWithKey(user, function (res) {
    var message = {
      rid: 'ankit',
      msg: 'Hi! This is for web client'
    };

    const handle = Meteor.subscribe('messages');

    Tracker.autorun(() => {
      const isReady = handle.ready();
      console.log(`Handle is ${isReady ? 'ready' : 'not ready'}`);
      console.log(handle);
    });
    Meteor.call('sendMessage', message);
  });
  console.log(Messages.findOne())
}

On the server-side, I’m getting this Error

Exception in queued task: RangeError: Maximum call stack size exceeded

Login / Sending message Methods are working fine. I’m not sure what I’m missing here, Though I’m able to do all this if I use MongoDB.

Thanks in advance, any comment will be appreciated.


#2

This: {connection: null} means don’t synchronise data between client and server.

What I think you want here is a “roll-your-own” publication. This may help (it discusses polling a REST endpoint, but the principle applies):


#3

Thank you @robfallows I think there should be a way of sending the message from a method call to the other clients without the using Database.

This {connection: null} is for creating a minimonog instance i.e in memory data. So it should be able fetch the data from minimongo on the server and added it to current publication queue.

If I will be getting messages from a REST API. There are following concequences:

  • Messages won’t get deliver in Real time there will be a time gap, It can’t be as Robust it should be.

  • I’ve to depend on other server, there may be chances or getting failure if one server is down.

  • I’ve to save the data in any of the DB, which I don’t want. If needed I will save in meteor’s mongo it self.


#4

You can send the results of a method call back to the calling client without any effort. If you want to “send the message from a method call to the other clients without the using Database.” then you will have to use pub/sub, and the technique outlined in that link is the way to do it.


#5

Hi, @robfallows I’ve tried altering that code, and now I’m able to get messages from one client to another client in real time. using the following update.

  Meteor.publish('messages', function(rid) {
    if (!this.userId) {
      return this.ready();
    }

    let finderHandle = Messages.find({
      $or: [
        {username: Meteor.users.findOne({_id: this.userId}).username},
        {rid: Meteor.users.findOne({_id: this.userId}).username}
      ]
    })

    finderHandle.observeChanges({
      added: (_id, record) => {
        this.added( 'messages',_id, record )
      },
      changed: (_id, record) => {
        this.changed( 'messages', _id, record)
      },
      removed: (_id, record) => {
        this.removed( 'messages',_id, record)
      }
    });

    this.onStop(() => {
      console.log("disconnected")
      // finderHandle.close(); // Giving an Error: finderHandle.close() function not found.
    })

    this.ready();
  });

Now the problem here is, when I disconnect and connect again, It is sending me all the previous messages as well. I want to remve that message as soon as it is delivered.
how can I handle this.removed event here?

also if I’m trying to use ‘this.onStop’ function finderHandle.close(); is giving me an error when a user disconnects saying this close function is undefined.


#6

Now I’m completely confused.

You said you wanted pub/sub without MongoDB and you have written something which seems to greatly complicate pub/sub with MongoDB.

:confused:


#7

yes, but it I’ve given connection: null which isn’t storing it to DB.


#8

@robfallows Please correct me if I’m wrong, what exactly it is happening behind the scenes.