mirror of
https://github.com/stablyai/orca.git
synced 2026-09-29 08:03:20 +00:00
216 lines
7.7 KiB
JavaScript
216 lines
7.7 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import { readFileSync } from 'node:fs'
|
|
import test from 'node:test'
|
|
import {
|
|
calculateRelayCloudSqlConnectionBudget,
|
|
readRelayCloudSqlConnectionBudget
|
|
} from './relay-cloud-sql-connection-budget.mjs'
|
|
|
|
// Why these numbers are this tight: the shared instance's 400 connections were already spoken
|
|
// for, and the relay shape below leaves exactly five. The gateway is sized to fit in four, two
|
|
// instances times a two-connection pool, and its rollout overlap of 23 stays under the API
|
|
// candidate's 65, so the Math.max is the API candidate rather than the gateway.
|
|
//
|
|
// `Deploy Relay Asia Topology` gates on `withinBudget == true`, so the single remaining
|
|
// connection is the whole margin. Anything that raises a pool or an instance count moves it.
|
|
test('production plus the push gateway keeps allowance and reserve below the ceiling', () => {
|
|
const report = readRelayCloudSqlConnectionBudget()
|
|
|
|
assert.deepEqual(report.consumers, { cells: 230, directors: 15, auth: 20, api: 50, push: 4 })
|
|
assert.deepEqual(report.asia, { cells: 3, poolMax: 10 })
|
|
assert.equal(report.configuredMaximum, 319)
|
|
assert.equal(report.rolloutOverlap.relayDirectorCandidate, 30)
|
|
assert.equal(report.rolloutOverlap.apiCandidate, 65)
|
|
assert.equal(report.rolloutOverlap.authCandidate, 35)
|
|
assert.equal(report.rolloutOverlap.pushCandidate, 23)
|
|
assert.equal(report.rolloutOverlap.relayCells, 15)
|
|
assert.equal(report.rolloutOverlap.retainedDirectorRollback, 15)
|
|
// The gateway does not set the maximum; the API candidate does, as it did before it existed.
|
|
assert.equal(report.rolloutOverlap.maximum, 65)
|
|
assert.equal(report.maintenanceAdminAllowance, 5)
|
|
assert.equal(report.explicitReserve, 10)
|
|
assert.equal(report.usableCeiling, 390)
|
|
assert.equal(report.operatingMaximum, 389)
|
|
assert.equal(report.remainingWithinUsableCeiling, 1)
|
|
assert.equal(report.budgetedTotal, 399)
|
|
assert.equal(report.unallocated, 1)
|
|
assert.equal(report.withinBudget, true)
|
|
})
|
|
|
|
// Why: the same relay shape without a push gateway is the before picture, and it stood at five
|
|
// connections clear. Holding it here keeps the gateway's cost visible as the four it takes,
|
|
// rather than letting drift elsewhere in the budget hide inside the same margin.
|
|
test('the same relay shape without the gateway stays inside the ceiling', () => {
|
|
const report = calculateRelayCloudSqlConnectionBudget({
|
|
cellPoolTotal: 200,
|
|
asiaCellCount: 3,
|
|
asiaPoolMax: 10,
|
|
directorInstances: 5,
|
|
directorPoolMax: 3,
|
|
authInstances: 2,
|
|
authPoolMax: 10,
|
|
apiInstances: 10,
|
|
apiPoolMax: 5,
|
|
pushInstances: 0,
|
|
pushPoolMax: 0,
|
|
maxConnections: 400,
|
|
maintenanceAdminAllowance: 5,
|
|
explicitReserve: 10
|
|
})
|
|
|
|
assert.equal(report.consumers.push, 0)
|
|
assert.equal(report.rolloutOverlap.maximum, 65)
|
|
assert.equal(report.operatingMaximum, 385)
|
|
assert.equal(report.remainingWithinUsableCeiling, 5)
|
|
assert.equal(report.withinBudget, true)
|
|
})
|
|
|
|
// Why: a tagged candidate is directly addressable and sits outside the service-wide cap, so both
|
|
// push revisions can reach the ceiling at once. The API and auth candidates add one copy; this
|
|
// one adds two, like the director candidate.
|
|
test('the push rollout scenario doubles the gateway draw over the retained director', () => {
|
|
const report = calculateRelayCloudSqlConnectionBudget({
|
|
cellPoolTotal: 0,
|
|
asiaCellCount: 0,
|
|
asiaPoolMax: 0,
|
|
directorInstances: 5,
|
|
directorPoolMax: 3,
|
|
authInstances: 0,
|
|
authPoolMax: 0,
|
|
apiInstances: 0,
|
|
apiPoolMax: 0,
|
|
pushInstances: 2,
|
|
pushPoolMax: 2,
|
|
maxConnections: 400,
|
|
maintenanceAdminAllowance: 5,
|
|
explicitReserve: 10
|
|
})
|
|
|
|
assert.equal(report.consumers.push, 4)
|
|
// 15 retained director rollback, plus the 4-connection draw counted twice.
|
|
assert.equal(report.rolloutOverlap.pushCandidate, 23)
|
|
})
|
|
|
|
test('fails closed when pool growth consumes the explicit reserve', () => {
|
|
const report = calculateRelayCloudSqlConnectionBudget({
|
|
cellPoolTotal: 200,
|
|
asiaCellCount: 3,
|
|
asiaPoolMax: 20,
|
|
directorInstances: 5,
|
|
directorPoolMax: 3,
|
|
authInstances: 2,
|
|
authPoolMax: 10,
|
|
apiInstances: 20,
|
|
apiPoolMax: 5,
|
|
pushInstances: 4,
|
|
pushPoolMax: 10,
|
|
maxConnections: 400,
|
|
maintenanceAdminAllowance: 5,
|
|
explicitReserve: 10
|
|
})
|
|
|
|
assert.equal(report.operatingMaximum, 555)
|
|
assert.equal(report.withinBudget, false)
|
|
})
|
|
|
|
test('excludes fenced cell pools and reads per-cell pool overrides', () => {
|
|
const report = readRelayCloudSqlConnectionBudget({
|
|
proposedAsiaCellCount: 1,
|
|
appConsumers: { authInstances: 1, authPoolMax: 10, apiInstances: 1, apiPoolMax: 5, maxConnections: 100 },
|
|
sources: {
|
|
productionTfvars: `
|
|
relay_max_instances = 1
|
|
relay_gce_fenced_cells = ["production-gce-c1"]
|
|
relay_gce_cells = {
|
|
"production-gce-c1" = { database_pool_max = 99
|
|
}
|
|
"production-gce-c2" = { database_pool_max = 4
|
|
}
|
|
}
|
|
`,
|
|
terraformVariables: [
|
|
'variable "relay_director_database_pool_max" { default = 3 }',
|
|
'variable "push_max_instances" { default = 1 }',
|
|
'variable "push_database_pool_max" { default = 2 }'
|
|
].join('\n'),
|
|
relayConfig: 'export const RELAY_DATABASE_POOL_MAX = 10'
|
|
},
|
|
maxConnections: 100,
|
|
maintenanceAdminAllowance: 1,
|
|
explicitReserve: 1
|
|
})
|
|
|
|
assert.equal(report.consumers.cells, 14)
|
|
// No push_max_instances in this tfvars, so the variable default of one instance holds.
|
|
assert.equal(report.consumers.push, 2)
|
|
assert.equal(report.operatingMaximum, 48)
|
|
assert.equal(report.budgetedTotal, 49)
|
|
})
|
|
|
|
// Why: production.tfvars overrides push_max_instances down to 2 while variables.tf still defaults
|
|
// to 4, so reading the default instead of the override would overstate the live draw by half.
|
|
test('a tfvars push_max_instances override wins over the variable default', () => {
|
|
const report = readRelayCloudSqlConnectionBudget({
|
|
proposedAsiaCellCount: 1,
|
|
appConsumers: { authInstances: 1, authPoolMax: 10, apiInstances: 1, apiPoolMax: 5, maxConnections: 100 },
|
|
sources: {
|
|
productionTfvars: `
|
|
relay_max_instances = 1
|
|
push_max_instances = 3
|
|
relay_gce_fenced_cells = []
|
|
relay_gce_cells = {
|
|
"production-gce-c2" = { database_pool_max = 4
|
|
}
|
|
}
|
|
`,
|
|
terraformVariables: [
|
|
'variable "relay_director_database_pool_max" { default = 3 }',
|
|
'variable "push_max_instances" { default = 1 }',
|
|
'variable "push_database_pool_max" { default = 2 }'
|
|
].join('\n'),
|
|
relayConfig: 'export const RELAY_DATABASE_POOL_MAX = 10'
|
|
},
|
|
maxConnections: 100,
|
|
maintenanceAdminAllowance: 1,
|
|
explicitReserve: 1
|
|
})
|
|
|
|
assert.equal(report.consumers.push, 6)
|
|
assert.equal(report.rolloutOverlap.pushCandidate, 15)
|
|
})
|
|
|
|
test('requires strict headroom below the physical ceiling', () => {
|
|
const report = calculateRelayCloudSqlConnectionBudget({
|
|
cellPoolTotal: 20,
|
|
asiaCellCount: 0,
|
|
asiaPoolMax: 10,
|
|
directorInstances: 1,
|
|
directorPoolMax: 3,
|
|
authInstances: 1,
|
|
authPoolMax: 10,
|
|
apiInstances: 1,
|
|
apiPoolMax: 5,
|
|
pushInstances: 1,
|
|
pushPoolMax: 2,
|
|
maxConnections: 50,
|
|
maintenanceAdminAllowance: 9,
|
|
explicitReserve: 3
|
|
})
|
|
|
|
assert.equal(report.budgetedTotal, 65)
|
|
assert.equal(report.withinBudget, false)
|
|
})
|
|
|
|
test('pages Relay channels when Cloud SQL backends consume headroom', () => {
|
|
const terraform = readFileSync(
|
|
new URL('../../infra/terraform/relay-observability.tf', import.meta.url),
|
|
'utf8'
|
|
)
|
|
const policy = terraform.match(
|
|
/resource "google_monitoring_alert_policy" "relay_cloud_sql_backends" \{([\s\S]*?)\n\}/
|
|
)?.[1]
|
|
|
|
assert.ok(policy)
|
|
assert.match(policy, /notification_channels\s*=\s*var\.relay_alert_notification_channels/)
|
|
})
|