Class InMemoryRateLimiter

java.lang.Object
com.codename1.backend.security.ratelimit.InMemoryRateLimiter
All Implemented Interfaces:
RateLimiter

public final class InMemoryRateLimiter extends Object implements RateLimiter

A limit kept in this process's memory: a token bucket per key.

RateLimiter logins = new InMemoryRateLimiter(5, 60);     // 5 a minute, per key

A key starts with permits tokens and gets them back at permits per period, evenly: a client may spend them all at once and is then let through at the steady rate, which is what "5 a minute" means to the person waiting.

The count is per process. A server run as several instances behind a load balancer has one count in each, so a client is allowed up to the limit times the number of instances. Where the limit is there to keep load down that is usually what is wanted. Where it is a security bound -- attempts at a password -- count somewhere the instances share, behind the RateLimiter interface. The counts are also gone when the process restarts.

Memory is bounded: no more than a set number of keys are remembered, 100000 unless set. A key whose bucket has refilled is forgotten, since forgetting it changes nothing; past the bound the keys idle longest are forgotten early, which gives such a key its tokens back sooner than it earned them. A flood of distinct keys therefore costs a bounded amount of memory, and the most it buys the flooder is the full bucket a new key starts with anyway.

  • Constructor Summary

    Constructors
    Constructor
    Description
    InMemoryRateLimiter(int permits, long periodSeconds)
     
    InMemoryRateLimiter(int permits, long periodSeconds, int maxKeys)
     
  • Method Summary

    Modifier and Type
    Method
    Description
    derive(String name, int permits, long periodSeconds)
    A limiter in this process with counts of its own, read on the same clock; the name is not needed to keep them apart.
    void
    Forgets what was counted under key, so the next request under it is counted from nothing.
    long
    How many seconds a request just refused under key should wait before trying again: what its Retry-After says.
    void
    setClock(Clock clock)
    Reads the time from clock instead of the machine.
    int
    How many keys are remembered now.
    boolean
    Counts one request under key.

    Methods inherited from class Object

    clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • InMemoryRateLimiter

      public InMemoryRateLimiter(int permits, long periodSeconds)
      Parameters:
      permits - how many requests a key may make in a period
      periodSeconds - the length of the period
    • InMemoryRateLimiter

      public InMemoryRateLimiter(int permits, long periodSeconds, int maxKeys)
      Parameters:
      maxKeys - the most keys remembered at once
  • Method Details

    • derive

      public RateLimiter derive(String name, int permits, long periodSeconds)
      A limiter in this process with counts of its own, read on the same clock; the name is not needed to keep them apart.
      Specified by:
      derive in interface RateLimiter
      Parameters:
      name - what keeps the new limiter's counts apart
      permits - how many requests a key may make in a period
      periodSeconds - the length of the period
    • setClock

      public void setClock(Clock clock)
      Reads the time from clock instead of the machine.
    • size

      public int size()
      How many keys are remembered now.
    • tryAcquire

      public boolean tryAcquire(String key)
      Description copied from interface: RateLimiter
      Counts one request under key.
      Specified by:
      tryAcquire in interface RateLimiter
      Returns:
      whether the request is within the limit
    • reset

      public void reset(String key)
      Description copied from interface: RateLimiter

      Forgets what was counted under key, so the next request under it is counted from nothing.

      A bound on wrong guesses uses this: the guess is counted before it is looked at, so that guesses made together cannot each be let through as the last one, and a right one hands the count back. A limiter that cannot forget does nothing here, which is what it does unless it says more; a right guess then costs what a wrong one does.

      Specified by:
      reset in interface RateLimiter
    • retryAfterSeconds

      public long retryAfterSeconds(String key)
      Description copied from interface: RateLimiter
      How many seconds a request just refused under key should wait before trying again: what its Retry-After says. One second unless the limiter knows better.
      Specified by:
      retryAfterSeconds in interface RateLimiter