Skip to content

Conversation

@hyp3rd
Copy link
Owner

@hyp3rd hyp3rd commented Feb 1, 2026

  • 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

- 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
Copilot AI review requested due to automatic review settings February 1, 2026 21:36
@hyp3rd hyp3rd self-assigned this Feb 1, 2026
Copy link

Copilot AI left a 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), and durable stats (optionally JSON) commands.
  • Register the new subcommands and update docs/examples in README.md.
  • Replace encoding/json with github.com/goccy/go-json and 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.

Comment on lines +15 to +20
type statsSnapshot struct {
Queues []queueCounts `json:"queues"`
TotalReady int64 `json:"total_ready"`
TotalProcessing int64 `json:"total_processing"`
Dead int64 `json:"dead"`
}
Copy link

Copilot AI Feb 1, 2026

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.

Copilot uses AI. Check for mistakes.
Comment on lines +66 to +82
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
Copy link

Copilot AI Feb 1, 2026

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.

Copilot uses AI. Check for mistakes.
Comment on lines +28 to +29
redis.call("HSET", taskKey, "updated_at_ms", now)

Copy link

Copilot AI Feb 1, 2026

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).

Suggested change
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

Copilot uses AI. Check for mistakes.
if err != nil {
return ewrap.Wrap(err, "delete task")
}

Copy link

Copilot AI Feb 1, 2026

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.

Suggested change
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")
}

Copilot uses AI. Check for mistakes.
@hyp3rd hyp3rd merged commit 8c765c2 into main Feb 1, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants