-
-
Notifications
You must be signed in to change notification settings - Fork 1
feat(workerctl): add durable requeue/delete/stats commands #41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Add `workerctl durable requeue` shortcut to requeue a queue directly - Add `workerctl durable delete` to delete a task (optionally also delete its hash) - Uses an embedded Lua script for the Redis-side delete behavior - Add `workerctl durable stats` with optional JSON output - Register the new durable subcommands in `cmd/workerctl/durable.go` - Switch JSON encoding to `github.com/goccy/go-json` and add dependency in `go.mod` - Update `README.md` with usage docs for requeue/delete/stats
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Adds new workerctl durable subcommands to operate on durable queues/tasks (requeue shortcut, delete, stats), updates CLI wiring and docs, and switches JSON encoding to github.com/goccy/go-json.
Changes:
- Add
durable requeue,durable delete(Lua-backed), anddurable stats(optionally JSON) commands. - Register the new subcommands and update docs/examples in
README.md. - Replace
encoding/jsonwithgithub.com/goccy/go-jsonand update dependencies/spellcheck.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| go.mod | Promote go-json to a direct dependency. |
| durable_redis.go | Switch JSON marshal/unmarshal import to go-json. |
| cspell.json | Add goccy to dictionary. |
| cmd/workerctl/durable_stats.go | New durable stats command with optional JSON output. |
| cmd/workerctl/durable_requeue.go | New durable requeue shortcut command. |
| cmd/workerctl/durable_get.go | Switch JSON encoder import to go-json. |
| cmd/workerctl/durable_dump.go | Switch JSON encoder import to go-json. |
| cmd/workerctl/durable_delete.go | New durable delete command using an embedded Redis Lua script. |
| cmd/workerctl/durable.go | Register new durable subcommands. |
| README.md | Document usage for requeue/delete/stats. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| type statsSnapshot struct { | ||
| Queues []queueCounts `json:"queues"` | ||
| TotalReady int64 `json:"total_ready"` | ||
| TotalProcessing int64 `json:"total_processing"` | ||
| Dead int64 `json:"dead"` | ||
| } |
Copilot
AI
Feb 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
statsSnapshot.Queues is []queueCounts, but queueCounts has unexported fields (name, ready, processing), so --json output will serialize each queue as {} (missing name/counts). Use an exported struct for JSON output (or export the fields on queueCounts) and map the internal counts into it.
| if opts.jsonOutput { | ||
| payload := statsSnapshot{ | ||
| Queues: counts, | ||
| TotalReady: totals.ready, | ||
| TotalProcessing: totals.processing, | ||
| Dead: deadCount, | ||
| } | ||
|
|
||
| err := json.NewEncoder(os.Stdout).Encode(payload) | ||
| if err != nil { | ||
| return ewrap.Wrap(err, "encode json") | ||
| } | ||
| } | ||
|
|
||
| printQueueCounts(counts, totals, deadCount) | ||
|
|
||
| return nil |
Copilot
AI
Feb 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When --json is set, the command encodes JSON and then still calls printQueueCounts, producing mixed JSON + human-readable output on stdout. Consider returning immediately after encoding (or printing human output to stderr) so --json output stays valid JSON.
| redis.call("HSET", taskKey, "updated_at_ms", now) | ||
|
|
Copilot
AI
Feb 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Lua delete script does HSET taskKey updated_at_ms unconditionally. If the task hash does not exist, this creates a new hash key for an unknown task, leaving behind a ghost :task:<id> record even though we're trying to delete. Add an EXISTS check before mutating taskKey, or only HSET when the hash exists (and skip it entirely when --delete-hash is used).
| redis.call("HSET", taskKey, "updated_at_ms", now) | |
| if deleteHash ~= "1" then | |
| local exists = redis.call("EXISTS", taskKey) | |
| if exists == 1 then | |
| redis.call("HSET", taskKey, "updated_at_ms", now) | |
| end | |
| end |
| if err != nil { | ||
| return ewrap.Wrap(err, "delete task") | ||
| } | ||
|
|
Copilot
AI
Feb 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
runDurableDelete always prints "deleted task " as long as the script executes, but the script always returns 1 and doesn't indicate whether anything was actually removed. This can report success for nonexistent IDs / wrong queue overrides. Consider having the script return a meaningful count (e.g., removed-from-ready/proc/dead and/or whether the hash existed) and use that to print an accurate message or return an error when nothing matched.
| deletedCount, err := resp.ToInt64() | |
| if err != nil { | |
| return ewrap.Wrap(err, "parse delete script result") | |
| } | |
| if deletedCount == 0 { | |
| return ewrap.New("no matching task found to delete") | |
| } |
workerctl durable requeueshortcut to requeue a queue directlyworkerctl durable deleteto delete a task (optionally also delete its hash)workerctl durable statswith optional JSON outputcmd/workerctl/durable.gogithub.com/goccy/go-jsonand add dependency ingo.modREADME.mdwith usage docs for requeue/delete/stats