3

I know client side _underscore.js can be used to throttle click rates, but how do you throttle calls server side? I thought of using the same pattern but unfortunately _throttle doesn't seem to allow for differentiating between Meteor.userId()'s.

Meteor.methods({
  doSomething: function(arg1, arg2){
    // how can you throttle this without affecting ALL users
  }
);
Stephan Tual
  • 2,617
  • 3
  • 27
  • 49

2 Answers2

6

Here's a package I've roughed up - but not yet submitted to Atmosphere (waiting until I familiarize myself with tinytest and write up unit tests for it).

https://github.com/zeroasterisk/Meteor-Throttle

Feel free to play with it, extend, fix and contribute (pull requests encouraged)

The concept is quite simple, and it only runs (should only be run) on the server.

You would first need to come up with a unique key for what you want to throttle...

eg: Meteor.userId() + 'my-function-name' + 'whatever'

This system uses a new Collection 'throttle' and some helper methods to: check, set, and purge records. There is also a helper checkThenSet method which is actually the most common pattern, check if we can do something, and the set a record that we did.

Usage

(Use Case) If your app is sending emails, you wouldn't want to send the same email over and over again, even if a user triggered it.

// on server
if (!Throttle.checkThenSet(key, allowedCount, expireInSec)) {
  throw new Meteor.Error(500, 'You may only send ' + allowedCount + ' emails at a time, wait a while and try again');
}
....

On Throttle Methods

  • checkThenSet(key, allowedCount, expireInSec) checks a key, if passes it then sets the key for future checks
  • check(key, allowedCount) checks a key, if less than allowedCount of the (unexpired) records exist, it passes
  • set(key, expireInSec) sets a record for key, and it will expire after expireInSec seconds, eg: 60 = 1 min in the future
  • purge() expires all records which are no longer within timeframe (automatically called on every check)

Methods (call-able)

  • throttle(key, allowedCount, expireInSec) --> Throttle.checkThenSet()
  • throttle-check(key, allowedCount) --> Throttle.check()
  • throttle-set(key, expireInSec) --> Throttle.set()
avalanche1
  • 3,154
  • 1
  • 31
  • 38
zeroasterisk
  • 2,199
  • 1
  • 23
  • 28
  • Note that [link-only answers](http://meta.stackoverflow.com/tags/link-only-answers/info) are discouraged, SO answers should be the end-point of a search for a solution (vs. yet another stopover of references, which tend to get stale over time). Please consider adding a stand-alone synopsis here, keeping the link as a reference. – kleopatra Oct 14 '13 at 22:34
3

there is not built in support for this currently in meteor, but its on the roadmap https://trello.com/c/SYcbkS3q/18-dos-hardening-rate-limiting

in theory you could use some of the options here Throttling method calls to M requests in N seconds but you would have to roll your own solution

Community
  • 1
  • 1
nate-strauser
  • 2,763
  • 1
  • 16
  • 16