tools: add send-test-push for one-shot Asynq push verification
Backend CI / Test (push) Has been cancelled
Backend CI / Contract Tests (push) Has been cancelled
Backend CI / Build (push) Has been cancelled
Backend CI / Lint (push) Has been cancelled
Backend CI / Secret Scanning (push) Has been cancelled

Tiny CLI that enqueues a notification:send_push task into Redis. The
worker picks it up and routes through internal/push/Client.SendToAll —
which is exactly the path used by HandleSmartReminder, HandleDailyDigest,
and any other in-process push, so a successful round-trip here proves the
production push pipeline end-to-end without waiting for the next cron tick.

Requires Redis to be reachable. Easiest path:

  kubectl -n honeydue port-forward svc/redis 6379:6379

  go run ./cmd/send-test-push --user-id 6 --title "..." --message "..."

The worker logs `Sending push notification...` followed by the APNs
batch result; failure modes (BadDeviceToken, circuit breaker, etc.)
surface as the same error_message rows the existing notif-diag tool
already reports on.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-05-01 08:59:51 -07:00
parent cb1dc383b4
commit ce4d49caef
2 changed files with 60 additions and 0 deletions
+1
View File
@@ -10,6 +10,7 @@ bin/
/admin
/admin-reset
/notif-diag
/send-test-push
!admin/
*.exe
*.exe~
+59
View File
@@ -0,0 +1,59 @@
// send-test-push enqueues a one-shot Asynq push notification task. The worker
// picks it up and routes it through internal/push/Client.SendToAll, which now
// hits APNs production. Verifies end-to-end that push delivery is working
// without waiting for the next cron tick.
//
// Usage:
//
// # Port-forward Redis from the cluster first:
// kubectl --kubeconfig=~/.kube/honeydue-k3s.yaml -n honeydue port-forward svc/redis 6379:6379
//
// # Then in another shell:
// go run ./cmd/send-test-push --user-id 6 --title "Test" --message "Hello from notif-diag"
package main
import (
"flag"
"fmt"
"os"
"strconv"
"github.com/hibiken/asynq"
"github.com/treytartt/honeydue-api/internal/worker/jobs"
)
func main() {
userID := flag.Uint("user-id", 0, "Target auth_user.id (required)")
title := flag.String("title", "Test push", "Notification title")
message := flag.String("message", "Hello from send-test-push", "Notification body")
redisAddr := flag.String("redis", "localhost:6379", "Redis host:port (use kubectl port-forward to reach the in-cluster redis)")
flag.Parse()
if *userID == 0 {
fmt.Fprintln(os.Stderr, "--user-id is required")
os.Exit(2)
}
task, err := jobs.NewSendPushTask(*userID, *title, *message, map[string]string{
"type": "test",
"user_id": strconv.FormatUint(uint64(*userID), 10),
})
if err != nil {
fmt.Fprintf(os.Stderr, "build task: %v\n", err)
os.Exit(1)
}
client := asynq.NewClient(asynq.RedisClientOpt{Addr: *redisAddr})
defer func() { _ = client.Close() }()
info, err := client.Enqueue(task, asynq.Queue("default"), asynq.MaxRetry(3))
if err != nil {
fmt.Fprintf(os.Stderr, "enqueue: %v\n", err)
os.Exit(1)
}
fmt.Printf("Enqueued task: id=%s queue=%s type=%s\n", info.ID, info.Queue, info.Type)
fmt.Printf("Tail worker logs to see the result:\n")
fmt.Printf(" kubectl --kubeconfig=~/.kube/honeydue-k3s.yaml -n honeydue logs deploy/worker --tail=20 -f\n")
}