{"id":"redis-set-get-with-ttl","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-set-get-with-ttl\n# version:       1.0.0\n# primitive:     code_execution\n# description:   SET and GET a key in Redis with TTL expiry, verify expiry behavior, and avoid the SETEX deprecation footgun\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#   set_ok       — true if SET succeeded\n#   get_ok       — true if GET returned correct value\n#   ttl_set      — TTL in seconds as configured\n#   ttl_verified — actual TTL returned by Redis\n#   expiry_ok    — true if TTL is within expected range\n#\n# MAST FAILURE MODES ADDRESSED:\n# FM-1.1 Disobey Task Specification        — atomic SET+EX used, not separate SET then EXPIRE\n# FM-3.3 Incorrect Verification            — TTL verified via TTL command, not assumed\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\nKEY    = \"checklist:ttl:test\"\nVALUE  = \"hello-checklist\"\nTTL    = 60  # seconds\n\nclient = redis_lib.Redis.from_url(REDIS_URL, decode_responses=True, socket_connect_timeout=10)\n\ntry:\n    # Cleanup\n    client.delete(KEY)\n\n    # 1. SET with TTL\n    # FOOTGUN: use SET key value EX seconds (atomic) — not separate SET then EXPIRE\n    # FOOTGUN: SETEX is deprecated since Redis 2.6 — use SET with EX parameter\n    set_ok = client.set(KEY, VALUE, ex=TTL)\n    print(f\"  SET {KEY} = '{VALUE}' EX {TTL}s → {set_ok}\")\n\n    # 2. GET\n    retrieved = client.get(KEY)\n    get_ok = retrieved == VALUE\n    print(f\"  GET {KEY} → '{retrieved}' (match={get_ok})\")\n\n    # 3. Verify TTL\n    # FOOTGUN: TTL returns -1 if key has no expiry, -2 if key doesn't exist\n    ttl_verified = client.ttl(KEY)\n    expiry_ok = 0 < ttl_verified <= TTL\n    print(f\"  TTL {KEY} → {ttl_verified}s (expected <= {TTL}s, expiry_ok={expiry_ok})\")\n\n    # Cleanup\n    client.delete(KEY)\n\nfinally:\n    client.close()\n\n# ─────────────────────────────────────────\n# POST_EXECUTION\n# ─────────────────────────────────────────\n\nassert set_ok, \"FAIL: SET returned falsy\"\nassert get_ok, f\"FAIL: GET returned '{retrieved}', expected '{VALUE}'\"\nassert expiry_ok, f\"FAIL: TTL={ttl_verified} out of expected range (0, {TTL}]\"\n\nresult = {\n    \"set_ok\":       bool(set_ok),\n    \"get_ok\":       get_ok,\n    \"ttl_set\":      TTL,\n    \"ttl_verified\": ttl_verified,\n    \"expiry_ok\":    expiry_ok,\n}\nprint(json.dumps(result, indent=2))\nprint(\"PASS\")\n"}