retry_count column and filter existed but counter was never incremented. Stuck commands always had retry_count=0 and always passed the WHERE retry_count < 5 filter, making the cap ineffective. Fix: Added RedeliverStuckCommandTx that sets retry_count = retry_count + 1 on stuck->sent re-delivery. GetCommands handler now uses MarkCommandSentTx for new commands (retry_count stays 0) and RedeliverStuckCommandTx for stuck re-delivery (retry_count increments). All 77 tests pass. DEV-029 resolved. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
106 lines
3.4 KiB
Go
106 lines
3.4 KiB
Go
package database_test
|
|
|
|
// stuck_command_retry_test.go — Tests for stuck command retry limit.
|
|
//
|
|
// F-B2-10 FIXED: retry_count column added (migration 029).
|
|
// GetStuckCommands filters retry_count < 5.
|
|
// RedeliverStuckCommandTx increments retry_count on re-delivery (DEV-029 fix).
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestStuckCommandHasNoMaxRetryCount(t *testing.T) {
|
|
// POST-FIX: retry_count column exists, filter in query, and increment wired.
|
|
migrationsDir := filepath.Join("migrations")
|
|
files, err := os.ReadDir(migrationsDir)
|
|
if err != nil {
|
|
t.Fatalf("failed to read migrations directory: %v", err)
|
|
}
|
|
|
|
hasRetryCount := false
|
|
for _, f := range files {
|
|
if !strings.HasSuffix(f.Name(), ".up.sql") {
|
|
continue
|
|
}
|
|
content, err := os.ReadFile(filepath.Join(migrationsDir, f.Name()))
|
|
if err != nil {
|
|
continue
|
|
}
|
|
src := strings.ToLower(string(content))
|
|
if strings.Contains(src, "agent_commands") && strings.Contains(src, "retry_count") {
|
|
hasRetryCount = true
|
|
}
|
|
}
|
|
|
|
if !hasRetryCount {
|
|
t.Error("[ERROR] [server] [database] F-B2-10 NOT FIXED: no retry_count column")
|
|
}
|
|
|
|
// Check GetStuckCommands for retry limit
|
|
cmdPath := filepath.Join("queries", "commands.go")
|
|
content, err := os.ReadFile(cmdPath)
|
|
if err != nil {
|
|
t.Fatalf("failed to read commands.go: %v", err)
|
|
}
|
|
|
|
src := string(content)
|
|
|
|
// Verify filter exists in GetStuckCommands
|
|
stuckIdx := strings.Index(src, "func (q *CommandQueries) GetStuckCommands")
|
|
if stuckIdx == -1 {
|
|
t.Fatal("[ERROR] [server] [database] GetStuckCommands function not found")
|
|
}
|
|
stuckBody := src[stuckIdx:]
|
|
if len(stuckBody) > 500 {
|
|
stuckBody = stuckBody[:500]
|
|
}
|
|
if !strings.Contains(strings.ToLower(stuckBody), "retry_count") {
|
|
t.Error("[ERROR] [server] [database] F-B2-10 NOT FIXED: GetStuckCommands has no retry filter")
|
|
}
|
|
|
|
// DEV-029: Verify RedeliverStuckCommandTx increments retry_count
|
|
if !strings.Contains(src, "RedeliverStuckCommandTx") {
|
|
t.Error("[ERROR] [server] [database] DEV-029 NOT FIXED: no RedeliverStuckCommandTx function")
|
|
}
|
|
redeliverIdx := strings.Index(src, "func (q *CommandQueries) RedeliverStuckCommandTx")
|
|
if redeliverIdx != -1 {
|
|
redeliverBody := src[redeliverIdx:]
|
|
if len(redeliverBody) > 300 {
|
|
redeliverBody = redeliverBody[:300]
|
|
}
|
|
if !strings.Contains(redeliverBody, "retry_count = retry_count + 1") {
|
|
t.Error("[ERROR] [server] [database] DEV-029 NOT FIXED: RedeliverStuckCommandTx does not increment retry_count")
|
|
}
|
|
}
|
|
|
|
t.Log("[INFO] [server] [database] F-B2-10 + DEV-029 FIXED: retry count wired end-to-end")
|
|
}
|
|
|
|
func TestStuckCommandHasMaxRetryCount(t *testing.T) {
|
|
// Verify: column exists, filter in query, and increment function exists
|
|
cmdPath := filepath.Join("queries", "commands.go")
|
|
content, err := os.ReadFile(cmdPath)
|
|
if err != nil {
|
|
t.Fatalf("failed to read commands.go: %v", err)
|
|
}
|
|
|
|
src := string(content)
|
|
|
|
// Must have RedeliverStuckCommandTx with retry_count increment
|
|
if !strings.Contains(src, "retry_count = retry_count + 1") {
|
|
t.Errorf("[ERROR] [server] [database] retry_count is never incremented.\n" +
|
|
"DEV-029: RedeliverStuckCommandTx must increment retry_count on re-delivery.")
|
|
}
|
|
|
|
// Must have retry_count < 5 filter
|
|
if !strings.Contains(src, "retry_count < 5") {
|
|
t.Errorf("[ERROR] [server] [database] no retry_count < 5 filter in stuck command queries")
|
|
}
|
|
|
|
t.Log("[INFO] [server] [database] F-B2-10 + DEV-029 FIXED: retry count capped at 5")
|
|
}
|