Files
orca/cloud/apps/relay/src/postgres-schema-concurrency-postgres.test.ts
Jinwoo Hong dd9eaa9585 fix(cloud): retry the committed-winner collision codes in relay schema startup (#18553)
* fix(cloud): retry the committed-winner collision codes in relay schema startup

`CREATE TABLE IF NOT EXISTS` only checks the name before the catalog inserts, so
the loser of a concurrent CREATE fails in one of two ways depending on timing:
on the catalog unique index (23505, which the startup retry already handled) or,
when the winner has committed by the time the loser reaches TypeCreate /
heap_create_with_catalog, on the name check those routines repeat (42710
duplicate type, 42P07 duplicate relation). The predicate treated the latter as
fatal, so a director could fail startup on a table it was about to find present.

This is what turned `postgres-schema-concurrency-postgres.test.ts` red on main
and on every relay PR (CI's shared runner loses the race more often than a dev
box): a throwaway diagnostic run in CI reported 42710 from TypeCreate and 42P07
from heap_create_with_catalog as the only rejection reasons.

Treat 42710/42P07 as retryable for `CREATE TABLE IF NOT EXISTS` and 42P07 for
`CREATE [UNIQUE] INDEX IF NOT EXISTS`; every other statement shape still fails
fast. The concurrency test now runs ten rounds and reports the loser's SQLSTATE
instead of a bare boolean.

* chore(cloud): allowlist the RFC 6455 example Sec-WebSocket-Key for upgrade tests

Cloud Verify's Secret scan runs gitleaks over --all refs, so the raw-socket
upgrade test on fix/relay-upgrade-malformed-uri (#18547) trips every cloud PR's
scan until its allowlist reaches main. Land the allowlist here first.
2026-09-03 21:20:27 -04:00

62 lines
2.2 KiB
TypeScript

import pg from 'pg'
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
import { openRelayDatabase, type RelayDatabase } from './database.js'
const databaseUrl = process.env.ORCA_RELAY_TEST_POSTGRES_URL
const describePostgres = databaseUrl ? describe : describe.skip
const schema = 'relay_schema_concurrency_test'
describePostgres('PostgreSQL schema concurrency', () => {
let scopedUrl = ''
beforeAll(async () => {
const client = new pg.Client({ connectionString: databaseUrl })
await client.connect()
try {
await client.query(`DROP SCHEMA IF EXISTS ${schema} CASCADE`)
await client.query(`CREATE SCHEMA ${schema}`)
} finally {
await client.end()
}
const url = new URL(databaseUrl!)
url.searchParams.set('options', `-c search_path=${schema}`)
scopedUrl = url.toString()
})
afterAll(async () => {
const client = new pg.Client({ connectionString: databaseUrl })
await client.connect()
try {
await client.query(`DROP SCHEMA IF EXISTS ${schema} CASCADE`)
} finally {
await client.end()
}
})
it('opens five directors when one new table is absent', async () => {
// Which catalog step the race loser fails on depends on scheduling, so run several rounds and
// keep the loser's SQLSTATE in the failure instead of a bare boolean.
for (let round = 0; round < 10; round += 1) {
const initial = await openRelayDatabase({ databaseUrl: scopedUrl, dataDir: '' })
await initial.query(`DROP TABLE relay_cell_legacy_fence_adoptions`)
await initial.close()
const results = await Promise.allSettled(
Array.from({ length: 5 }, async (): Promise<RelayDatabase> =>
await openRelayDatabase({ databaseUrl: scopedUrl, dataDir: '' })
)
)
const databases = results.flatMap((result) =>
result.status === 'fulfilled' ? [result.value] : []
)
await Promise.all(databases.map(async (database) => await database.close()))
const rejections = results.flatMap((result) =>
result.status === 'rejected'
? [{ round, code: (result.reason as { code?: unknown }).code, message: String(result.reason) }]
: []
)
expect(rejections).toEqual([])
}
}, 60_000)
})