Meteor CPU load: Method call vs Subscription - meteor

What is the CPU costless between sending data to a client via publish/subscription and via Method calls?

My answer is going to assume that you simply want to send data to the client:
It depends on what you want to do. If you want realtime updates the subscriptions model is ideal when compares to call a server method each 5 seconds or so.
When you don't want reactive updates, simply pass the flag reactive:false in your find() query.
Methods are used when you want, for example, to return the results on an aggregation (because meteor doesn't support reactivity for aggregations), to get updates for unsupported operator ($where is not supported yet), etc.
Usually the bottlenecks exists in the application design/architecture.

Related

Multiple Firestore changes with batch vs cloud functions

In a chat app, if I add a new message to the messages collection, I also need to update that particular chat's document in another collection to show the last message and the time when it was sent. Right now I am triggering a cloud function every time a new message comes, in order to update the metadata for the chat. Am I doing the right thing or would it be more appropriate to use Batched writes instead?
There is a difference that you might be aware of when using one approach vs. the other. When using a batch write, according to the official documentation:
You can execute multiple write operations as a single batch that contains any combination of set(), update(), or delete() operations. A batch of writes completes atomically and can write to multiple documents.
This means that those simultaneous updates that are made in this atomic way, either all updates succeed or all updates fail.
In case you are using a function that is triggered once a message is sent, it means that you are performing two separate actions. The first one is to send a message and the second one is to update some metadata once the message is successfully sent. In this case, you can send a message but your function may fail, according to the official documentation:
By default, without retries enabled, the semantics of executing a background function are "best effort." This means that while the goal is to execute the function exactly once, this is not guaranteed.
This are the reasons why background functions fail to complete:
On rare occasions, a function might exit prematurely due to an internal error, and by default the function might or might not be automatically retried.
More typically, a background function may fail to successfully complete due to errors thrown in the function code itself. Some of the reasons this might happen are as follows:
The function contains a bug and the runtime throws an exception.
The function cannot reach a service endpoint, or times out while trying to reach the endpoint.
The function intentionally throws an exception (for example, when a parameter fails validation).
When functions written in Node.js return a rejected promise or pass a non-null value to a callback.
The workaround in this case, is to use retry to handle transient errors.

Meteor - calling serverside methods from client

Are Meteor.methods they only way to call server-side functions from the client?
http://docs.meteor.com/#/full/meteor_methods
the docs don't make it clear that they are they only way, but the fact that they exist seems to imply they are the only way. What is their purpose?
There are several ways to communicate back and forth between the server and client in Meteor :
Using Meteor.methods to perform Remote Method Invokation on the server, these calls are initiated by the client, ask for a computation to be performed on the server and receive a result.
Using the Pub/Sub mechanism, the server publishes a set of data and the client is subscribing to a subset of this data, being notified in real-time of data-updates taking place in the server and thus receiving modifications.
Using plain old HTTP requests with the HTTP module.
So Meteor.methods are not the only way to execute some code on the server upon a client request.
Their purpose is usually to update the database by providing new values for server-side collections, as a matter of fact, client-side collection inserts and updates are implemented as Meteor.methods.
The Pub/Sub mechanism is used to propagate DB updates to every connected client and to make sure they receive only the minimal subset they need.
The HTTP communication is used by the server to send the initial source code (HTML/JS/CSS) of the app on load time as well as performing standard operations such as requesting and downloading a file.

Can Meteor call a method on the server twice if the client gets disconnected?

In LivedataConnection, line 357, there's a comment that says:
// Sends the method message to the server. May be called additional times if
// we lose the connection and reconnect before receiving a result.
Does this mean that if a client calls a method and gets disconnected before the method returns, it will re-call that message when it reconnects? What if that method isn't idempotent?
Basically, yes, as of version 1.0. Meteor methods are not idempotent. I've reported this issue, as have others, and it's basically confirmed by a core developer:
https://github.com/meteor/meteor/issues/2407#issuecomment-52375372
The best way to fix this in most cases is to try and write a unique key to the database, associating with a method request, or to make use of some other clever conditional database updates. There are some discussions about how to do that in these threads:
https://groups.google.com/d/msg/meteor-talk/j1YF7JO5Rdo/cYHR5kbhC8UJ
https://stackoverflow.com/a/26430334/586086

Meteor threading style clarification

Meteor's documentation states:
In Meteor, your server code runs in a single thread per request, not in the asynchronous callback style typical of Node
Do they actually mean?
A) the server is running multiple threads in parallel (which seems unusual within the Node.js ecosystem)
or
B) There is still only a single thread within an evented server and each request is processed sequentially, at least until it makes calls to resources outside the server - like the datastore, at which point the server itself is handling the callbacks while it processes with other requests, so you don't have to write/administer the callbacks yourself.
Brad, your B is correct.
Meteor uses fibers internally. As you said, there's only one thread inside an evented server, but when you do (eg) a database read, Fibers yields and control quickly gets back to the event loop. So your code looks like:
doc = MyCollection.findOne(id);
(with a hidden "yield to the event loop, come back when the doc is here") rather than
MyCollection.findOne(id, function (err, doc) {
if (err)
handle(err);
process(doc);
});
Error handling in the fiber version also just uses standard JavaScript exceptions instead of needing to check an argument every time.
I think this leads to an easier style of code to read for business logic which wants to take a bunch of actions which depend on each other in series. However, most of Meteor's synchronous APIs optionally take callbacks and become asynchronous, if you'd like to use the async style.

node.js asynchronous initialization issue

I am creating a node.js module which communicates with a program through XML-RPC. The API for this program changed recently after a certain version. For this reason, when a client is created (createClient) I want to ask the program its version (through XML-RPC) and base my API definitions on that.
The problem with this is that, because I do the above asynchronously, there exists a possibility that the work has not finished before the client is actually used. In other words:
var client = program.createClient();
client.doSomething();
doSomething() will fail because the API definitions have not been set, I imagine because HTTP XML-RPC response has not returned from the program.
What are some ways to remedy this? I want to be able to have a variable named client and work with that, as later I will be calling methods on it to get information (which will be returned via a callback).
Set it up this way:
program.createClient(function (client) {
client.doSomething()
})
Any time there is IO, it must be async. Another approach to this would be with a promise/future/coroutine type thing, but imo, just learning to love the callback is best :)

Resources