From d60da43cd7a39631d5595501f96801a9252bc028 Mon Sep 17 00:00:00 2001 From: Molecule AI Core-BE Date: Tue, 12 May 2026 15:58:38 +0000 Subject: [PATCH] fix(handlers): add timeouts to all DB operations in integration tests Add 10s timeouts to integrationDB and setupIntegrationFixtures DB operations, and a 5s timeout to the cleanup DELETEs. The raw TCP mock server was confirmed working (tests pass in 5-8s when they pass), but some CI runs hang for 2+ minutes. Adding timeouts ensures that if DB operations block, the test fails cleanly with a timeout message rather than hanging the CI job. This also makes the tests more resilient to transient postgres slowness under CI runner load. Co-Authored-By: Claude Opus 4.7 --- .../delegation_executor_integration_test.go | 23 +++++++++++++------ .../delegation_ledger_integration_test.go | 8 +++++-- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/workspace-server/internal/handlers/delegation_executor_integration_test.go b/workspace-server/internal/handlers/delegation_executor_integration_test.go index 98f708fa..f86dfebe 100644 --- a/workspace-server/internal/handlers/delegation_executor_integration_test.go +++ b/workspace-server/internal/handlers/delegation_executor_integration_test.go @@ -163,6 +163,7 @@ func buildHTTPResponse(statusCode int, body string) []byte { // Returns a cleanup function the test should defer. func setupIntegrationFixtures(t *testing.T, conn *sql.DB) func() { t.Helper() + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) for _, ws := range []struct { id string name string @@ -171,10 +172,11 @@ func setupIntegrationFixtures(t *testing.T, conn *sql.DB) func() { {testSourceID, "test-source", nil}, {testTargetID, "test-target", nil}, } { - if _, err := conn.ExecContext(context.Background(), + if _, err := conn.ExecContext(ctx, `INSERT INTO workspaces (id, name, parent_id) VALUES ($1::uuid, $2, $3) ON CONFLICT (id) DO NOTHING`, ws.id, ws.name, ws.parentID, ); err != nil { + cancel() t.Fatalf("seed workspace %s: %v", ws.id, err) } } @@ -183,31 +185,36 @@ func setupIntegrationFixtures(t *testing.T, conn *sql.DB) func() { "delegation_id": testDelegationID, "task": "do work", }) - if _, err := conn.ExecContext(context.Background(), ` + if _, err := conn.ExecContext(ctx, ` INSERT INTO activity_logs (workspace_id, activity_type, method, source_id, target_id, request_body, status) VALUES ($1, 'delegate', 'delegate', $1, $2, $3::jsonb, 'pending') ON CONFLICT DO NOTHING `, testSourceID, testTargetID, string(reqBody)); err != nil { + cancel() t.Fatalf("seed activity_logs: %v", err) } - if _, err := conn.ExecContext(context.Background(), ` + if _, err := conn.ExecContext(ctx, ` INSERT INTO delegations (delegation_id, caller_id, callee_id, task_preview, status) VALUES ($1, $2::uuid, $3::uuid, 'do work', 'queued') ON CONFLICT (delegation_id) DO NOTHING `, testDelegationID, testSourceID, testTargetID); err != nil { + cancel() t.Fatalf("seed delegations: %v", err) } + cancel() return func() { - conn.ExecContext(context.Background(), + ctx2, cancel2 := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel2() + conn.ExecContext(ctx2, `DELETE FROM activity_logs WHERE workspace_id = $1 AND request_body->>'delegation_id' = $2`, testSourceID, testDelegationID) - conn.ExecContext(context.Background(), + conn.ExecContext(ctx2, `DELETE FROM delegations WHERE delegation_id = $1`, testDelegationID) - conn.ExecContext(context.Background(), + conn.ExecContext(ctx2, `DELETE FROM workspaces WHERE id IN ($1, $2)`, testSourceID, testTargetID) } } @@ -216,8 +223,10 @@ func setupIntegrationFixtures(t *testing.T, conn *sql.DB) func() { // delegation, or fails the test if the row is not found. func readDelegationRow(t *testing.T, conn *sql.DB) (status, preview, errorDetail string) { t.Helper() + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() var prev, errDet sql.NullString - err := conn.QueryRowContext(context.Background(), + err := conn.QueryRowContext(ctx, `SELECT status, result_preview, error_detail FROM delegations WHERE delegation_id = $1`, testDelegationID, ).Scan(&status, &prev, &errDet) diff --git a/workspace-server/internal/handlers/delegation_ledger_integration_test.go b/workspace-server/internal/handlers/delegation_ledger_integration_test.go index 78c0a874..802a2d16 100644 --- a/workspace-server/internal/handlers/delegation_ledger_integration_test.go +++ b/workspace-server/internal/handlers/delegation_ledger_integration_test.go @@ -64,12 +64,16 @@ func integrationDB(t *testing.T) *sql.DB { if err != nil { t.Fatalf("open: %v", err) } - if err := conn.Ping(); err != nil { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + if err := conn.PingContext(ctx); err != nil { t.Fatalf("ping: %v", err) } // Each test gets a fresh table state — fail loud if cleanup fails so // a bad test doesn't pollute the next one. - if _, err := conn.ExecContext(context.Background(), `DELETE FROM delegations`); err != nil { + ctx2, cancel2 := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel2() + if _, err := conn.ExecContext(ctx2, `DELETE FROM delegations`); err != nil { t.Fatalf("cleanup: %v", err) } // Wire the package-level db.DB so production helpers (recordLedgerInsert,