How meteor handles SaaS (pub/sub)?

Hi,
How meteor handles pub/sub in a SaaS context?

The (simple example!) problem is:
Imagine a “data table” for all customers records and a “data table” for all customers purchases. How can the web app notify the right customer (after a subscribe) about the purchase invoice already available and not all customers? Is it possible to subscribe based on channel contents instead of channel name?

How to do this?

Hob

Can you give a bit more context? What do you mean with “notify”? Like publishing the the right content to the right customer? If that’s the case, you need to add a customer_id to each purchase and to each user that works on behalf of that customer. The customer would then subscribe to a invoices publication. In that publication you use “this.userId” to fetch the user record. Then you use the customer_id in the user record to filter invoices. Whenever the invoice is available it will automatically be published to the right users. Example:

Meteor.publish("invoices", function() {
    const user = Meteor.users.findOne(this.userId);
    if(!user) {
        throw new Meteor.Error("403", "You must be logged in";
    }

    return Invoices.find({customer_id: user.customer_id});
});

Thanks!
I think is more or less that but looking to your source code, what prevents all clients from receiving the result of the findOne instruction? I am assuming that all client have subscribed to “invoices”, right?

Sorry, here a more specific scenario:

imagine customer with id 1 has some products available on his eStore (available on the client app)
imagine customer with id 2 has some products available on his eStore (available on the client app)
customer id 1 has 2 users that have installed the client app with full product synch at first run…
customer id 2 has 5 users that have installed the client app with full product synch at first run…

app is the same/shared! each user on startup says with store he want to connect to (imagine!)

Now, imagine that customer id 1 (admin!) changes the description of a specific product. Hence, the 2 related users or apps must be updated for that specific product change!

But the other 5 users belonging to the other customer (id2) should not receive the update notification, because the none of the customer id 2 products have changed.

Again, all users share the same app which is customized no the first run (imagine).

Well, is it possible on the client app instance to subscribe on datasets (e.g. products) based on customer id?

Ok just to be sure:

From the customer perspective

  1. There is one database with a “default” product list.
  2. Each new customer will have that list
  3. Depending on the customers needs, they can update that list (updating, removing, adding products)

From the app user perspective

  1. User visits / downloads the app for the first time
  2. Initial product list gets loaded into the app
  3. All customer specific changes (additions, removals, changes) get applied to the products

Is this correct?

No…

From the customer perspective

  1. There is one database with one product table (cust_id as foreign key).
  2. Each new customer will have that list. No, each new product record is indexed to each customer (cust_id)
  3. Depending on the customers needs, they can update that list (updating, removing, adding products). Humm… Each customer, via web app can manage their products (change price, etc). On the web app each customer only see his products in the shared products table

From the app user perspective

  1. User visits / downloads the app for the first time, right!
  2. Initial product list gets loaded into the app. Hummm… when user runs app for first time it choosed whisch store it wants to deal with (e.g. customer id)
  3. All customer specific changes (additions, removals, changes) get applied to the products.Humm… Each customer manage his products products and if there is any user that have the app installed to that customer/store, those users/app instances must receive updates because related products have changed.

Imagine, the first customer could have a store of souvenirs and the other customer can have a store of books, other customer can have a store of computers, all stored in the “products table”.

By the way is my SaaS concept wrong? In SaaS the software is shared right?, and data is different from user to user, right?

Can all this be imlemented in other way i am not aware of (hence, avoiding all that specific updates (pub/sub))?

Is this correct?

Without getting bogged down in the nitty-gritty, deliver of per-user data is exactly what Meteor is designed to do.

Right, but my question is which subscribe instruction should i use to achieve that? subscribe the whole products table? Or do I have to have a products table per customer?

@cloudspider has already answered that. You publish a subset of documents based on some criteria (in this case at least the userid). Each client that subscribes sees a different subset, because they’re different users.

So if this is your publication (based off @cloudspider’s):

Meteor.publish("invoices", function() {
    return Invoices.find({customer_id: this.userId});
});

The subscription might be:

Meteor.subscribe('invoices');

Each user gets only their invoices.

Really? Ok… May be i am missing some meteor “mechanics”…

When using traditional messaging brokers when all subscribe the channel (e.g. invoices) all will receive data published in that channel…

But if subscription is done using channel and content criteria, only the clients which criteria apply receive the data…

Meteor.subscribe(‘invoices’); => for me this seems to be subscribing topic invoices even though sometimes only specific records are published from the publishing side…

thanks…

1 Like

Thanks for that link.
I am going carefully read it and experiment it…

1 Like

Hold-on. I think you mean this:

On the client

//Set this id whenever the user selects a customer
//Optionally use the u2622:persistent-session package to let the session survive refreshes or logouts
Session.set("customer_id", "someId");

Template.products.onCreated(function() {
  //Subscribe to a customer specific product list. 
  //Whenever the user switches customer, 
  //the subscription will automatically change and therefore update the client collections with data 
  this.autorun(() => {
    this.subscribe("invoices", Session.get("customer_id"));
  });
});

On the server

Meteor.publish("invoices", function(customer_id) {
    if(!customer_id) {
        throw new Meteor.Error("400", "A customer_id is required");
    }

    const customer = Customers.findOne(customer_id);
    if(!customer) {
        throw new Meteor.Error("404", "No such customer in our system");
    }
    return Invoices.find({customer_id: customer_id});
});

Look, I don’t understand your exact requirement - I was paring the code to it’s absolute minimum to show you the principle.

If you now have enough information to run with it that’s :smile: - I’m not going to write your app for you.

:joy: I agree with you. The reason why I did it was I because I was a bit bored.

Sorry, I am not trying to finding someone to write my code.
(“principle” is universal ! It is simply the Pub / Sub approach! Only primitives change according to languages. That was what i was looking for…)

I was simple try to understand the way to subcribe using criteria and cloudspider kindly have shown me that it is possible (in the same way we all do using threaded messaging brokers)…

(Now, i am sure that I can start planning the implementation using meteor instead of java)

Thanks to all

2 Likes