Skip to content

Commit e2ab1ef

Browse files
ksarangmathclaude
andcommitted
test: pin MultiXact-free fused acceptance and the ready-index claim plan
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent 31f4d91 commit e2ab1ef

2 files changed

Lines changed: 147 additions & 0 deletions

File tree

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//go:build integration
2+
3+
package executionstore_test
4+
5+
import (
6+
"context"
7+
"testing"
8+
9+
"github.com/jackc/pgx/v5"
10+
"github.com/jackc/pgx/v5/pgxpool"
11+
12+
"github.com/omnara-ai/omnara/internal/modelenvelope"
13+
"github.com/stretchr/testify/require"
14+
)
15+
16+
func TestFusedAcceptanceDoesNotCreateMultiXacts(t *testing.T) {
17+
for _, continued := range []bool{true, false} {
18+
name := "release"
19+
if continued {
20+
name = "continue"
21+
}
22+
t.Run(name, func(t *testing.T) {
23+
ctx := t.Context()
24+
f, input := fusedModelFixture(t, ctx)
25+
if continued {
26+
input.Output.ProviderResponse.Normalized.StopReason = modelenvelope.StopReasonMaxTokens
27+
}
28+
_, err := f.Store.pool.Exec(ctx, `CREATE EXTENSION pageinspect;
29+
ALTER TABLE agents SET (autovacuum_enabled=false);
30+
ALTER TABLE agent_runtime_locks SET (autovacuum_enabled=false)`)
31+
require.NoError(t, err)
32+
multixacts := func(table string) int {
33+
t.Helper()
34+
var n int
35+
require.NoError(t, f.Store.pool.QueryRow(ctx, `
36+
SELECT count(*) FROM generate_series(0,pg_relation_size($1::text::regclass)/current_setting('block_size')::int-1) block
37+
CROSS JOIN LATERAL heap_page_items(get_raw_page($1,block)) item
38+
CROSS JOIN LATERAL heap_tuple_infomask_flags(item.t_infomask,item.t_infomask2) flags
39+
WHERE flags.raw_flags @> ARRAY['HEAP_XMAX_IS_MULTI']`, table).Scan(&n))
40+
return n
41+
}
42+
for _, table := range []string{"agents", "agent_runtime_locks"} {
43+
require.Zero(t, multixacts(table), table+" before")
44+
}
45+
counter := &fusedQueryCounter{}
46+
config := f.Store.pool.Config()
47+
config.ConnConfig.Tracer = counter
48+
pool, err := pgxpool.NewWithConfig(ctx, config)
49+
require.NoError(t, err)
50+
defer pool.Close()
51+
measured := newIntegrationStore(pool)
52+
transition, err := measured.Execution().AcceptModelOutputAndAdvance(ctx, input)
53+
t.Logf("fused %s statements=%d", name, counter.statements)
54+
bound := 20
55+
if continued {
56+
bound = 29
57+
}
58+
require.LessOrEqual(t, counter.statements, bound)
59+
require.NoError(t, err)
60+
require.Nil(t, transition.Fallback)
61+
require.Equal(t, continued, transition.Continued)
62+
for _, table := range []string{"agents", "agent_runtime_locks"} {
63+
n := multixacts(table)
64+
t.Logf("%s MultiXact tuples after fused acceptance: %d", table, n)
65+
require.Zero(t, n, table)
66+
}
67+
})
68+
}
69+
}
70+
71+
type fusedQueryCounter struct{ statements int }
72+
73+
func (c *fusedQueryCounter) TraceQueryStart(
74+
ctx context.Context, _ *pgx.Conn, _ pgx.TraceQueryStartData,
75+
) context.Context {
76+
c.statements++
77+
return ctx
78+
}
79+
func (*fusedQueryCounter) TraceQueryEnd(context.Context, *pgx.Conn, pgx.TraceQueryEndData) {}
80+
func (*fusedQueryCounter) TraceBatchStart(ctx context.Context, _ *pgx.Conn, _ pgx.TraceBatchStartData) context.Context {
81+
return ctx
82+
}
83+
func (c *fusedQueryCounter) TraceBatchQuery(context.Context, *pgx.Conn, pgx.TraceBatchQueryData) {
84+
c.statements++
85+
}
86+
func (*fusedQueryCounter) TraceBatchEnd(context.Context, *pgx.Conn, pgx.TraceBatchEndData) {}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//go:build integration
2+
3+
package agentexecution_test
4+
5+
import (
6+
"encoding/json"
7+
"os"
8+
"strings"
9+
"testing"
10+
11+
"github.com/google/uuid"
12+
"github.com/stretchr/testify/require"
13+
)
14+
15+
func TestClaimReadyIndexPlan(t *testing.T) {
16+
f := migratedExecutionFixture(t)
17+
ctx := t.Context()
18+
ids := make([]uuid.UUID, 10000)
19+
for i := range ids {
20+
ids[i] = uuid.New()
21+
}
22+
_, err := f.pool.Exec(ctx, `
23+
INSERT INTO agents(id,root_agent_id,org_id,project_id,state,current_config_id,created_at,updated_at)
24+
SELECT id,id,$2,$3,'active',$4,statement_timestamp(),statement_timestamp() FROM unnest($1::uuid[]) id`,
25+
ids, f.org, f.project, f.config)
26+
require.NoError(t, err)
27+
_, err = f.pool.Exec(ctx, `INSERT INTO agent_wakeups(agent_id,ready_at,updated_at)
28+
SELECT id,statement_timestamp()-interval '1 minute',statement_timestamp() FROM unnest($1::uuid[]) id`, ids[:5000])
29+
require.NoError(t, err)
30+
_, err = f.pool.Exec(ctx, `
31+
INSERT INTO agent_runtime_locks(id,agent_id,worker_process_id,started_at,renewed_at,lease_expires_at)
32+
SELECT gen_random_uuid(),id,$2,statement_timestamp(),statement_timestamp(),statement_timestamp()+interval '90 seconds'
33+
FROM unnest($1::uuid[]) id`, ids[5000:], uuid.New())
34+
require.NoError(t, err)
35+
_, err = f.pool.Exec(ctx, `ANALYZE agents; ANALYZE agent_wakeups; ANALYZE agent_runtime_locks`)
36+
require.NoError(t, err)
37+
sql, err := os.ReadFile("../../queries/agent_inputs.sql")
38+
require.NoError(t, err)
39+
query := strings.Split(string(sql), "-- name: LockClaimableAgentWakeup")[0]
40+
tx, err := f.pool.Begin(ctx)
41+
require.NoError(t, err)
42+
defer func() { _ = tx.Rollback(ctx) }()
43+
_, err = tx.Exec(ctx, `SET LOCAL plan_cache_mode=force_generic_plan`)
44+
require.NoError(t, err)
45+
var raw []byte
46+
require.NoError(t, tx.QueryRow(ctx, "EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) "+query).Scan(&raw))
47+
t.Logf("claim EXPLAIN: %s", raw)
48+
var plan []struct {
49+
Plan struct {
50+
SharedHitBlocks int `json:"Shared Hit Blocks"`
51+
SharedReadBlocks int `json:"Shared Read Blocks"`
52+
}
53+
}
54+
require.NoError(t, json.Unmarshal(raw, &plan))
55+
require.NotContains(t, string(raw), `"Node Type": "Sort"`)
56+
require.NotContains(t, string(raw), `"Node Type": "Hash"`)
57+
require.NotContains(t, string(raw), `"Node Type": "Hash Join"`)
58+
require.Contains(t, string(raw), "agent_wakeups_global_ready_idx")
59+
buffers := plan[0].Plan.SharedHitBlocks + plan[0].Plan.SharedReadBlocks
60+
require.LessOrEqual(t, buffers, 40)
61+
}

0 commit comments

Comments
 (0)