music on atproto
plyr.fm
1#!/usr/bin/env -S uv run --script
2# /// script
3# requires-python = ">=3.11"
4# dependencies = ["redis"]
5# ///
6"""check recent docket task runs.
7
8usage:
9 ./scripts/docket_runs.py # uses DOCKET_URL from env
10 ./scripts/docket_runs.py --env staging # uses staging redis
11 ./scripts/docket_runs.py --env production # uses production redis
12 ./scripts/docket_runs.py --limit 20 # show more runs
13"""
14
15import argparse
16import os
17
18import redis
19
20
21def main():
22 parser = argparse.ArgumentParser(description="check docket task runs")
23 parser.add_argument(
24 "--env",
25 choices=["local", "staging", "production"],
26 default="local",
27 help="environment to check (default: local, uses DOCKET_URL)",
28 )
29 parser.add_argument(
30 "--limit", type=int, default=10, help="number of runs to show (default: 10)"
31 )
32 args = parser.parse_args()
33
34 # get redis url
35 if args.env == "local":
36 url = os.environ.get("DOCKET_URL", "redis://localhost:6379")
37 elif args.env == "staging":
38 url = os.environ.get("DOCKET_URL_STAGING")
39 if not url:
40 print("error: DOCKET_URL_STAGING not set")
41 print("hint: flyctl proxy 6380:6379 -a plyr-redis-stg")
42 print(" export DOCKET_URL_STAGING=redis://localhost:6380")
43 return 1
44 elif args.env == "production":
45 url = os.environ.get("DOCKET_URL_PRODUCTION")
46 if not url:
47 print("error: DOCKET_URL_PRODUCTION not set")
48 print("hint: flyctl proxy 6381:6379 -a plyr-redis")
49 print(" export DOCKET_URL_PRODUCTION=redis://localhost:6381")
50 return 1
51
52 print(f"connecting to {args.env}...")
53 r = redis.from_url(url)
54
55 # get all run keys
56 keys = r.keys("plyr:runs:*")
57 if not keys:
58 print("no runs found")
59 return 0
60
61 print(f"found {len(keys)} total runs, showing last {args.limit}:\n")
62
63 for key in sorted(keys, reverse=True)[: args.limit]:
64 data = r.hgetall(key)
65 run_id = key.decode().split(":")[-1]
66
67 # extract fields safely
68 function = data.get(b"function", b"?").decode()
69 state = data.get(b"state", b"?").decode()
70 started = (
71 data.get(b"started_at", b"").decode()[:19]
72 if data.get(b"started_at")
73 else "?"
74 )
75 completed = (
76 data.get(b"completed_at", b"").decode()[:19]
77 if data.get(b"completed_at")
78 else "-"
79 )
80 # state emoji
81 emoji = {"completed": "✓", "failed": "✗", "running": "⋯"}.get(state, "?")
82
83 print(
84 f"{emoji} {run_id[:8]} {function:<20} {state:<10} {started} → {completed}"
85 )
86
87 return 0
88
89
90if __name__ == "__main__":
91 raise SystemExit(main())