Browse Source

Update ratelimit.py docstring; add Redis service to docker-compose

ratelimit.py: fix module docstring to reflect current _NAMESPACE resolution
  (settings.POD_NAMESPACE, not K8s SA files read inside the middleware).

docker-compose.yaml:
  - Add saplredis service (redis:7-alpine, no persistence, 512 MB maxmemory,
    allkeys-lru, 4 databases, same policy as k8s ConfigMap).
  - Add REDIS_URL=redis://saplredis:6379 and CACHE_BACKEND=redis to the
    sapl service so local docker-compose runs use Redis out of the box.
  - sapl depends_on now includes saplredis.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
rate-limiter-2026
Edward Ribeiro 3 weeks ago
parent
commit
85e971ae9b
  1. 34
      docker/docker-compose.yaml
  2. 11
      sapl/middleware/ratelimit.py

34
docker/docker-compose.yaml

@ -18,6 +18,7 @@ services:
- "5433:5432"
networks:
- sapl-net
saplsolr:
image: solr:8.11
restart: always
@ -32,6 +33,34 @@ services:
- "8983:8983"
networks:
- sapl-net
saplredis:
image: redis:7-alpine
restart: always
container_name: redis
labels:
NAME: "redis"
command: >
redis-server
--save ""
--appendonly no
--maxmemory 512mb
--maxmemory-policy allkeys-lru
--maxmemory-samples 10
--maxclients 1000
--timeout 300
--tcp-keepalive 60
--hz 20
--lazyfree-lazy-eviction yes
--lazyfree-lazy-expire yes
--lazyfree-lazy-server-del yes
--databases 4
--protected-mode no
ports:
- "6379:6379"
networks:
- sapl-net
sapl:
image: sapl:local
# build:
@ -57,20 +86,25 @@ services:
IS_ZK_EMBEDDED: 'True'
ENABLE_SAPN: 'False'
TZ: America/Sao_Paulo
REDIS_URL: redis://saplredis:6379
CACHE_BACKEND: redis
volumes:
- sapl_data:/var/interlegis/sapl/data
- sapl_media:/var/interlegis/sapl/media
depends_on:
- sapldb
- saplsolr
- saplredis
ports:
- "80:80"
networks:
- sapl-net
networks:
sapl-net:
name: sapl-net
driver: bridge
volumes:
sapldb_data:
sapl_data:

11
sapl/middleware/ratelimit.py

@ -16,11 +16,12 @@ Decision flow (per request):
All decisions are no-ops when RATELIMIT_DRY_RUN=True (logged only).
Degrades gracefully to non-atomic counting when Redis is unavailable.
Tenant namespace (_NAMESPACE) is resolved once at module load from:
1. POD_NAMESPACE env var (K8s Downward API preferred)
2. K8s service-account namespace file (always present in-cluster)
3. 'global' (local development fallback)
Since each pod serves exactly one tenant, this is a startup constant
_NAMESPACE is settings.POD_NAMESPACE, resolved once at startup:
- K8s: start.sh reads the k8s namespace from the Downward API env var
or the service-account namespace file, writes it to .env as POD_NAMESPACE.
- Bare-metal / VM / docker-compose: defaults to the machine hostname
(socket.gethostbyname_ex result computed in settings.py).
Since a deployment serves exactly one tenant, this is a startup constant
no per-request lookup is needed or correct.
"""

Loading…
Cancel
Save