-
Notifications
You must be signed in to change notification settings - Fork 0
sosiouxme/throttle
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
= Throttle A memcached-based throttle - do something after a limit has been reached globally within a certain time period. == Why it is useful Frequently you may wish to restrict your application from doing too much of something. Some good examples are: * Keeping your API users from hammering the API (either deliberately or accidentally) * Spacing out expensive operations (perhaps as an API user) * Shutting out brute force hackers who make lots of requests trying to guess passwords, CAPTCHAs, etc. This class provides persistent throttles with rolling historical event counts maintained in a global memcache (so that distributed apps can share them). It is highly configurable and robust. == Basic usage: require 'rubygems' require 'memcache' require 'throttle' Throttle.memcache = MemCache.new('localhost:11211') t = Throttle.new {|count| raise 'ETooMuch' if count >= 10} 10.times { t.record_event } # -> raises 'ETooMuch' == Requirements Throttle requires the Ruby-MemCache rubygem. It also requires that you have a memcached running; you must supply the cache object to the class. For development, the rspec gem is required for testing. == public methods === memcache=(cache) Class method for supplying the memcache handle. Technically it can be any cache object with get, set and incr methods that work the same as memcache. This method must be called once prior to instantiating any throttles. === new(name = '', args={}) === new(name = '', args={}) {|count| ...} All arguments are optional, but the throttle will not do much by default. * name (default "") Uniquely identifying throttle name - should be unique globally. Any throttle created globally against the same memcache with the same name will share the same event count. Good bases for a name include account IDs, IP addresses, class + method names, etc. * :intervals (default 1) Number of intervals to use for counting. With a single interval, the count will be reset after each time period. With multiple intervals, the intervals will expire serially and counts in the remaining intervals will be included in the total, for a more even throttle. * :interval_secs (default 60) Lifetime of an interval's active service. After this many seconds a new interval will be created for counting, and if the maximum number of intervals is exceeded, the oldest will expire. The defaults configure a throttle that resets the count every minute. * Fixnum => Proc Range => Proc :always => Proc Callback procedure(s) to run when current count matches. It is called with one or two parameters: first the count, second the throttle object itself. If multiple callbacks match, they are called in indeterminate order. If a block is supplied, it is treated as if it had been passed as the :always => argument. It is assumed that every throttle object with the same name will be configured with the same intervals and timing (though by different instances or even different applications), but this is not verified. You will get unreliable results if you do otherwise. === #record_event(count = 1) === #incr(count = 1) Increments the current count and calls configured callbacks or block accordingly. Note that if the increment is by an amount other than 1, numeric and ranged thresholds may be skipped over and their callbacks not called. == Other usage You may find it helpful to override #test_threshold(count) - this method is called every time the count is incremented. Normally it tries to call the block or callbacks supplied at instantiation, but you may wish to hardwire the behavior instead. == Reliability Throttle deals gracefully with memcache failures by silently ignoring them. The throttle won't record events or test thresholds if memcache is unavailable or failing for some reason. It will simply do nothing so that your application proceeds normally. Throttle (by careful use of memcache's add and incr functionality) should avoid all race conditions that might otherwise be encountered, with one exception: at creation of a new interval it is possible that two throttles might summarize previous intervals at slightly different times and thus come up with a different total. In that case, whichever sum is stored first is used by all; it's possible this might result in threshold crossings being repeated, but should not allow any to be skipped. == TODO * Sane methods for determining the current count without incrementing * Allow callbacks/block to be configured after instantiation * See if anyone cares :-)
About
Ruby memcached-based throttle
Resources
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published