Use Meteor Methods like a boss!

Maciej Stasiełuk, Vazco

Meteor Impact Hackathon 2022

Tips & tricks to get more out of your Meteor Methods

About me

  • Developer with 15+ years of experience
  • I've been working with Meteor since 2012
  • CTO @ Vazco - a software development company located in Poland
  • We have developed and delivered dozens of Meteor apps over the years

Agenda

  1. What are Meteor Methods?
  2. Methods lifecycle
  3. The Validated Method idea
  4. Security implications
  5. Things you may not know a.k.a Tips & Tricks

What are Meteor Methods?

I assume that you know the basics.

 

If not, please check out Meteor University, which gives an excellent introduction to the concept:

university.meteor.com

…but let's make a quick recap :)

What are Meteor Methods?

Meteor implementation of RPC:
Remote Procedure Calls

The idea itself goes back to the 1980s!

It is a form of client-server interaction where the client can invoke some code directly on the server.

REST

Methods vs REST

+ Optimistic UI

+ Guaranteed execution order

- No HTTP cache & other stateless benefits

- Less popular: less tooling, interoperability, etc.

Methods lifecycle

  1. Simulation runs on the client (if it exists)
  2. DDP message is sent to the server
  3. The Method runs on the server
  4. DDP message is sent back to the client with a result
  5. Meteor does his magic and propagates any appropriate changes made by the Method to the clients that are subscribing to that data
  6. The last DDP message is sent, marking the end of operation - only then the callback fires and changes from the previous step are being reflected

Validated Methods

The ValidatedMethod

package

Official package:

mdg:validated-method

 

Around 120 lines of code

(most of it related to mixins support)

 

 

The idea

  • Structure methods in a more standardized way.
  • Validate all arguments with a schema (hence the name)
  • Separate business logic from validation (a.k.a. two-tiered methods pattern) for easier testing.
  • Reuse patterns common across the app, e.g. authorization, logging, documentation…

My recommendation

  • Build on top of the ValidatedMethod package or the idea itself.
  • Make it as easy to use in your app as possible.
  • Embed common patterns: promisification, authorization, logging, documentation… 
  • Make it yours.

Security

Arguments validation

  • Never trust the client!
     
  • Always check arguments
    • ValidatedMethod validation
    • `check` package
    • Any other form of verification

NoSQL injection

Mongo is also susceptible to query injections.

You should not only check argument type (e.g., a string) but also content before using it in a query.

Meteor.methods({
  removePost({ id }) {
    Posts.remove({ _id: id });
  }
});
Meteor.call('removePost', { id: { $ne: 'p0wn' });
Posts.remove({ _id: { $ne: 'p0wn'} });

DDoS attacks

Your server can be overloaded by Method requests.

 

To prevent this, you can implement Throttling with the DDPRateLimiter package.

Various Tips & Tricks you may not know about

Loading data from Methods

Not everything must be reactive!

 

You can improve the scaling capabilities of your apps by fetching some data with Methods (similar to how you would do with REST).

 

With a neat trick, you can still retain MiniMongo features.

APM

The Methods can be a big part of the perceived performance of your app.

Monitoring and understanding bottlenecks are crucial to improve scaling and performance.

Tools like APM in Galaxy Professional plans or MontiAPM can help you with that.

Server-side only Methods?

Do your methods contain secret code or execute proprietary algorithms you don't want to share publicly?

Do your Methods always start with isClient/isSimulation check?

 

Maybe putting them in the server only part of your app would be better.

Optimistic UI is not mandatory!

Calling a Method from another Method

There are cases where chaining Methods one from another can be helpful.

The idea is simple - call a Method from a body of another one.

 

The authorization/connection will be shared between chained methods.

The simulation will execute correctly (if both methods are available for the client).

Named or unnamed arguments for methods?

With the Validated Method pattern, all variables are passed as named arguments (in the first argument of a function).

This pattern is worth using even if not going for the Validated Methods.

 

It enables us to easily add and deprecate arguments, improving application maintenance over time. 

Client-side flow

Do you often find repeating code each time you call a Method?

Do you need cross app features, like a notification/toast when Method succeeds/fails?

Do you call Methods based on a result of another Method?

 

If so, think about introducing an action pattern to encapsulate those features in a single place.

Promisify your Method calls

Methods due to backward compatibility use the callback pattern, but it is very easy to promisify it for your convince. 

const callMethod = (name, args) => new Promise((resolve, reject) => {
  Meteor.call(name, args, (err, res) => {
    err ? reject(err) : resolve(res);
  });
});

callMethod('myMethod', { id: 1 })
  .then(res => console.log(res))
  .catch(err => console.error(err));

Know your Errors

There are three ways to handle errors in your Methods:

  1. Plain JavaScript Errors - those will be reported to a client without any details.
  2. Meteor.Error - with it, we can provide additional details to the Client, e.g. to show in a notification.
  3. ValidationError - a subset of the above, to handle arguments or form validations.

this.unblock()

By default, Methods are executed in the order they arrive (for a given connection) and wait for the previous one to end.

This is a good behavior but can lead to bottlenecks when we have a long-running Method, e.g., generating a report.

 

In such a case, we can use this.unblock() to bail out of the queue and don't block other requests.

Auto-retries

A less-known fact: Meteor auto-retries your Method calls in case of network issues.

This is a rare case, but your Methods must be resistant to it by making them idempotent.

 

Most Methods are by default because the ID generation algorithm prevents inserting or removing a document twice.

But on some occasions (e.g., counters with $inc), this should be handled on the app level. 

Further reading / watching

Thank you!

You can catch me at maciej.stasieluk@vazco.eu

Use Meteor Methods like a boss!

By Maciej

Use Meteor Methods like a boss!

Presentation for Meteor Impact Hackathon 2022

  • 226