{"id":"redis-rate-limit-sliding-window","version":"1.0.0","primitive":"code_execution","description":"Redis connection URL e.g. \"redis://localhost:6379\"","registry_refs":["redis"],"tags":[],"solves":[],"auth_required":true,"verified":false,"last_verified":"null","next_check":"2026-07-30","eval_result":"null","eval_env":"null","mast":[],"ref":"https://arxiv.org/abs/2503.13657","inputs":[{"name":"REDIS_URL","required":true,"description":"Redis connection URL e.g. \"redis://localhost:6379\""}],"executable":"# ============================================\n# checklist:     redis-rate-limit-sliding-window\n# version:       1.0.0\n# primitive:     code_execution\n# description:   Implement a sliding window rate limiter in Redis using sorted sets with atomic Lua script\n# registry_refs: redis\n# auth_required: true\n# verified:      false\n# last_verified: null\n# next_check:    2026-07-30\n# eval_result:   null\n# eval_env:      null\n#\n# inputs:\n#   - name: REDIS_URL\n#     required: true\n#     description: Redis connection URL e.g. \"redis://localhost:6379\"\n#\n# OUTPUTS:\n#   allowed_count  — requests allowed within the window\n#   blocked_count  — requests blocked (rate limit exceeded)\n#   window_seconds — rate limit window size\n#   max_requests   — max requests allowed per window\n#\n# MAST FAILURE MODES ADDRESSED:\n# FM-1.1 Disobey Task Specification        — atomic Lua script prevents race conditions\n# FM-1.3 Step Repetition                   — sliding window handles burst retries correctly\n# FM-3.3 Incorrect Verification            — actual allow/block counts verified against expected\n#\n# ref: https://arxiv.org/abs/2503.13657\n# ============================================\n\nimport sys\nimport os\nimport subprocess\nimport time\nimport urllib.request\nimport json\n\n# ─────────────────────────────────────────\n# PRE_EXECUTION\n# ─────────────────────────────────────────\n\nfor attempt in range(2):\n    try:\n        req = urllib.request.Request(\n            \"https://checklist.day/api/registry/redis\",\n            headers={\"User-Agent\": \"checklist-agent/1.0\"}\n        )\n        with urllib.request.urlopen(req, timeout=10) as resp:\n            registry = json.loads(resp.read())\n            break\n    except Exception as e:\n        if attempt == 1:\n            print(f\"ABORT: registry unreachable — {e}\")\n            sys.exit(1)\n        time.sleep(2)\n\nwarnings = registry.get(\"warnings\", [])\nif warnings:\n    print(\"[redis] WARNINGS:\")\n    for w in warnings if isinstance(warnings, list) else [warnings]:\n        print(f\"  ⚠ {w}\")\n\n# ─────────────────────────────────────────\n# EXECUTION\n# ─────────────────────────────────────────\n\nsubprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", \"-q\", \"redis>=5.0.0\"])\n\nimport redis as redis_lib\n\nREDIS_URL = os.environ.get(\"REDIS_URL\")\nif not REDIS_URL:\n    print(\"ABORT: REDIS_URL env var not set\")\n    sys.exit(1)\n\nWINDOW_SECONDS = 10\nMAX_REQUESTS   = 5\nKEY_PREFIX     = \"checklist:ratelimit\"\n\nclient = redis_lib.Redis.from_url(REDIS_URL, decode_responses=True, socket_connect_timeout=10)\n\n# Sliding window rate limiter using sorted set\n# FOOTGUN: use Lua script for atomicity — ZREMRANGEBYSCORE + ZADD + EXPIRE is a race condition without Lua\nRATE_LIMIT_SCRIPT = \"\"\"\nlocal key = KEYS[1]\nlocal now = tonumber(ARGV[1])\nlocal window = tonumber(ARGV[2])\nlocal max_requests = tonumber(ARGV[3])\nlocal request_id = ARGV[4]\n\n-- Remove requests outside the sliding window\nredis.call('ZREMRANGEBYSCORE', key, 0, now - window * 1000)\n\n-- Count current requests in window\nlocal count = redis.call('ZCARD', key)\n\nif count < max_requests then\n    -- Allow: add this request\n    redis.call('ZADD', key, now, request_id)\n    redis.call('PEXPIRE', key, window * 1000)\n    return 1\nelse\n    return 0\nend\n\"\"\"\n\nrate_limiter = client.register_script(RATE_LIMIT_SCRIPT)\n\ntry:\n    # Cleanup\n    client.delete(f\"{KEY_PREFIX}:user_123\")\n\n    allowed_count = 0\n    blocked_count = 0\n\n    # Send MAX_REQUESTS + 3 requests — first MAX_REQUESTS should be allowed, rest blocked\n    total_requests = MAX_REQUESTS + 3\n    for i in range(total_requests):\n        now_ms = int(time.time() * 1000)\n        result = rate_limiter(\n            keys=[f\"{KEY_PREFIX}:user_123\"],\n            args=[now_ms, WINDOW_SECONDS, MAX_REQUESTS, f\"req_{i}_{now_ms}\"]\n        )\n        if result == 1:\n            allowed_count += 1\n            print(f\"  request {i+1}: ALLOWED ({allowed_count}/{MAX_REQUESTS})\")\n        else:\n            blocked_count += 1\n            print(f\"  request {i+1}: BLOCKED (rate limit exceeded)\")\n\n    # Cleanup\n    client.delete(f\"{KEY_PREFIX}:user_123\")\n\nfinally:\n    client.close()\n\n# ─────────────────────────────────────────\n# POST_EXECUTION\n# ─────────────────────────────────────────\n\nassert allowed_count == MAX_REQUESTS, f\"FAIL: expected {MAX_REQUESTS} allowed, got {allowed_count}\"\nassert blocked_count == 3, f\"FAIL: expected 3 blocked, got {blocked_count}\"\n\nresult = {\n    \"allowed_count\":  allowed_count,\n    \"blocked_count\":  blocked_count,\n    \"window_seconds\": WINDOW_SECONDS,\n    \"max_requests\":   MAX_REQUESTS,\n}\nprint(json.dumps(result, indent=2))\nprint(\"PASS\")\n"}