View Source Creating Backends

See Hammer.Backend.ETS for a realistic example of a Hammer Backend module.

Backends for Hammer are expected to implement the Hammer.Backend behaviour, and be named something like Hammer.Backend.Foo. Several instances of the backend worker will be started as a worker pool (using the poolboy library), and so backend processes should not assume that there is only one instance of this server process.

The Hammer.Backend behaviour

The expected backend api is as follows:

  • args: Keyword list of configuration.

The expiry_ms key is considered essential, as the backend process should delete expired buckets somehow. Depending on how the backend implements cleanup, the cleanup_interval_ms key may be required. Other keys are for the backend developer to choose, but for example, if the backend were using a database called FooDB to store buckets, then an appropriate key would be foodb_config.

Example:

  Hammer.Backend.Foo.start_link(expiry_ms: 60_000 * 60,
                                cleanup_interval_ms: 60_000 * 10,
                                foodb_config: [host: "localhost"])

count_hit(pid, key, timestamp)

  • pid: pid of the backend process being called
  • key: The key of the current bucket, in the form of a tuple {bucket::integer, id::String}.
  • timestamp: The current timestamp (integer)

This function should increment the count in the bucket by 1.

Returns: Either a Tuple of {:ok, count} where count is the current count of the bucket, or {:error, reason}.

count_hit(pid, key, timestamp, increment)

  • pid: pid of the backend process being called
  • key: The key of the current bucket, in the form of a tuple {bucket::integer, id::String}.
  • timestamp: The current timestamp (integer)
  • increment: The number by which to increment the bucket

This function should increment the count in the bucket by the specified increment.

Returns: Either a Tuple of {:ok, count} where count is the current count of the bucket, or {:error, reason}.

get_bucket(pid, key)

  • pid: pid of the backend process being called
  • key: The key of the current bucket, in the form of a tuple {bucket::integer, id::String}.

Returns: Either a tuple of {:ok, bucket}, where bucket is a tuple of {key, count, created_at, updated_at}, key is, as usual, a tuple of {bucket_number, id}, count is the count of hits in the bucket, created_at and updated_at are integer timestamps, or {:error, reason}

delete_buckets(pid, id)

  • pid: pid of the backend process being called
  • id: rate-limit id (string) to delete

This should delete all existing buckets associated with the supplied id.

Returns: Either {:ok, count}, or {:error, reason}