Skip to main content

README.md

# HammerBackendEredisCluster

A clustered-Redis backend for the [Hammer](https://github.com/ExHammer/hammer)
rate-limiter (Hammer v7+), built on
[eredis_cluster](https://github.com/Nordix/eredis_cluster).

Keys embed a `{hash tag}` so every window of a key maps to the same cluster
slot — the reason to pick this over the single-node official
[hammer-backend-redis](https://github.com/ExHammer/hammer-backend-redis).

## Installation

Add `hammer_backend_eredis_cluster` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:hammer_backend_eredis_cluster, "~> 2.0"},
    {:hammer, "~> 7.0"}
  ]
end
```

> 2.0.0 is also mirrored in the `loopsocial` org repo (`hexpm:loopsocial`),
> where it was first published while public package ownership was being
> restored — consumers pinned there can stay or drop the `organization:`
> option at their leisure.

Using Hammer 6? Stay on `{:hammer_backend_eredis_cluster, "~> 1.0"}` — 2.0 is
the Hammer 7 port and drops the v6 `Hammer.Backend` behaviour (see the
CHANGELOG).

## Usage

Define a rate limiter and start it (typically under your supervision tree):

```elixir
defmodule MyApp.RateLimit do
  use Hammer, backend: Hammer.EredisCluster
end

# The cluster connection is managed elsewhere
# (e.g. `config :eredis_cluster, init_nodes: [...]`):
MyApp.RateLimit.start_link([])

# Or let the limiter establish the connection:
MyApp.RateLimit.start_link(
  servers: [{"127.0.0.1", 7001}, {"127.0.0.1", 7002}],
  options: [username: "myuser", password: "mypassword"]
)

# Allow 10 requests per minute:
case MyApp.RateLimit.hit("user_123", :timer.minutes(1), 10) do
  {:allow, _count} -> :ok
  {:deny, retry_ms} -> {:error, {:rate_limited, retry_ms}}
end
```

`use Hammer, backend: Hammer.EredisCluster` accepts `:cluster` (eredis_cluster
name, default `:eredis_cluster_default`), `:prefix` (Redis key prefix, default:
the module name) and `:algorithm` (only `:fix_window`). See the
`Hammer.EredisCluster` module docs.

## Documentation

On hexdocs: [https://hexdocs.pm/hammer_backend_eredis_cluster/](https://hexdocs.pm/hammer_backend_eredis_cluster/)

## Run tests locally

Tests need a real Redis cluster. Either `docker-compose up -d` (see
docker-compose.yml) and run tests with
`REDIS_CLUSTER_NODES=redis-master-1:6379,redis-master-2:6379,redis-master-3:6379`,
or start three local cluster-mode nodes on ports 7001-7003 (the default
`REDIS_CLUSTER_NODES`):

```bash
for p in 7001 7002 7003; do
  redis-server --port $p --cluster-enabled yes --cluster-config-file /tmp/rc/node-$p.conf \
    --dir /tmp/rc --daemonize yes --save "" --appendonly no
done
redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 \
  --cluster-replicas 0 --cluster-yes
mix test
```

## Getting Help

If you're having trouble, open an issue on this repo.