import { performance } from 'node:perf_hooks'; import fs from 'node:fs/promises'; import path from 'node:path'; import { pathToFileURL } from 'node:url'; import pg from 'pg'; import { DESTRUCTIVE_TEST_CONFIRMATION, assertDestructiveTestDatabase, describeDatabaseTarget, resolveDestructiveTestConfirmation, } from './lib/destructive-test-database-guard.js'; const { Client } = pg; export const CAPACITY_NAMESPACE = 'tiku.student-capacity.v1'; export const DEFAULT_TENANT_SLUG = 'capacity-test-students-100k'; export const MAX_STUDENT_COUNT = 100_000; export const DEFAULT_STUDENT_COUNT = 100_000; export const DEFAULT_BATCH_SIZE = 10_000; export const DEFAULT_ITERATIONS = 10; export const DEFAULT_WARMUP_ITERATIONS = 3; export const DEFAULT_PAGE_LIMIT = 100; export const DEFAULT_OUTPUT_DIR = 'docs/refactor/performance-reports'; const MODES = new Set(['plan', 'seed', 'benchmark', 'run', 'evidence', 'cleanup', 'smoke']); const TENANT_SLUG_PATTERN = /^capacity-test-[a-z0-9](?:[a-z0-9-]{0,47}[a-z0-9])?$/; const BLOCKED_TARGET_PATTERN = /(?:^|[-_.])tikupro(?:-pg)?(?:$|[-_.])/i; function argumentValue(argv, name) { const directIndex = argv.indexOf(name); if (directIndex >= 0) return String(argv[directIndex + 1] || '').trim(); const prefix = `${name}=`; const direct = argv.find(value => value.startsWith(prefix)); return direct ? String(direct).slice(prefix.length).trim() : ''; } function integerOption(value, fallback, { name, min, max }) { if (value === '') return fallback; if (!/^\d+$/.test(value)) throw new Error(`${name} must be an integer`); const parsed = Number(value); if (!Number.isSafeInteger(parsed) || parsed < min || parsed > max) { throw new Error(`${name} must be between ${min} and ${max}`); } return parsed; } function validateTenantSlug(value) { const slug = String(value || '').toLowerCase(); if (!TENANT_SLUG_PATTERN.test(slug)) { throw new Error('tenant slug must match capacity-test-* and contain only lowercase letters, numbers, and hyphens'); } return slug; } export function parseCapacityOptions(argv = process.argv.slice(2), env = process.env) { const mode = argumentValue(argv, '--mode') || 'plan'; if (!MODES.has(mode)) throw new Error(`unsupported mode: ${mode}`); const options = { mode, databaseUrl: String(env.DATABASE_URL || '').trim(), tenantSlug: validateTenantSlug( argumentValue(argv, '--tenant-slug') || env.CAPACITY_TENANT_SLUG || DEFAULT_TENANT_SLUG, ), count: integerOption(argumentValue(argv, '--count'), DEFAULT_STUDENT_COUNT, { name: 'count', min: 10, max: MAX_STUDENT_COUNT, }), batchSize: integerOption(argumentValue(argv, '--batch-size'), DEFAULT_BATCH_SIZE, { name: 'batch-size', min: 100, max: 20_000, }), iterations: integerOption(argumentValue(argv, '--iterations'), DEFAULT_ITERATIONS, { name: 'iterations', min: 1, max: 100, }), warmupIterations: integerOption( argumentValue(argv, '--warmup-iterations'), DEFAULT_WARMUP_ITERATIONS, { name: 'warmup-iterations', min: 0, max: 20 }, ), pageLimit: integerOption(argumentValue(argv, '--limit'), DEFAULT_PAGE_LIMIT, { name: 'limit', min: 1, max: 500, }), outputDir: argumentValue(argv, '--output-dir') || env.CAPACITY_OUTPUT_DIR || DEFAULT_OUTPUT_DIR, confirmation: resolveDestructiveTestConfirmation(env, argv), }; if (mode !== 'plan' && !options.databaseUrl) { throw new Error('DATABASE_URL is required outside plan mode'); } return options; } function safeTarget(databaseUrl) { if (!databaseUrl) return null; const target = describeDatabaseTarget(databaseUrl); const normalizedHost = target.host.replace(/^\[(.*)\]$/, '$1').toLowerCase(); if ( ['127.0.0.1', 'localhost', '::1'].includes(normalizedHost) && target.port === '5432' ) { throw new Error('Refusing tenant student capacity operation: local port 5432 is reserved for tikupro-pg'); } for (const value of [target.host, target.database, target.user]) { if (BLOCKED_TARGET_PATTERN.test(value)) { throw new Error('Refusing tenant student capacity operation: tikupro-pg targets are forbidden'); } } return target; } function normalizePlanText(value) { return String(value || '').replace(/\s+/g, ' ').trim(); } function percentile(values, target) { if (!values.length) return 0; const sorted = [...values].sort((a, b) => a - b); const index = Math.ceil((target / 100) * sorted.length) - 1; return sorted[Math.max(0, Math.min(sorted.length - 1, index))]; } function round(value) { return Math.round(Number(value || 0) * 1000) / 1000; } function containsSearchPattern(value) { return `%${String(value).replace(/[\\%_]/g, match => `\\${match}`)}%`; } function studentLegacyId(tenantSlug, ordinal) { return `${CAPACITY_NAMESPACE}:${tenantSlug}:${String(ordinal).padStart(6, '0')}`; } function capacityPlan(options) { return { schemaVersion: 1, mode: options.mode, dryRun: options.mode === 'plan', target: safeTarget(options.databaseUrl), fixture: { namespace: CAPACITY_NAMESPACE, tenantSlug: options.tenantSlug, requestedStudents: options.count, batchSize: options.batchSize, tables: ['public.platform_users', 'public.tenant_memberships', 'public.student_profiles'], }, benchmark: { cases: ['first-page', 'deep-cursor', 'name-substring', 'phone-substring', 'email-substring'], iterations: options.iterations, warmupIterations: options.warmupIterations, pageLimit: options.pageLimit, explain: 'EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON)', }, applyRequirement: `--confirm=${DESTRUCTIVE_TEST_CONFIRMATION}`, }; } async function acquireHarnessLock(client, tenantSlug) { const result = await client.query( 'select pg_try_advisory_lock(hashtext($1)) as acquired', [`${CAPACITY_NAMESPACE}:${tenantSlug}`], ); if (result.rows[0]?.acquired !== true) { throw new Error(`capacity tenant ${tenantSlug} is already being modified or benchmarked`); } } async function releaseHarnessLock(client, tenantSlug) { await client.query('select pg_advisory_unlock(hashtext($1))', [`${CAPACITY_NAMESPACE}:${tenantSlug}`]); } async function loadManagedTenant(client, tenantSlug) { const result = await client.query( ` select id, slug::text as slug, name, owner_user_id as "ownerUserId", metadata from public.tenants where slug = $1::citext limit 1 `, [tenantSlug], ); return result.rows[0] || null; } function assertManagedTenant(tenant, tenantSlug) { const marker = tenant?.metadata?.capacityHarness; if ( !tenant || marker?.namespace !== CAPACITY_NAMESPACE || marker?.managed !== true || marker?.tenantSlug !== tenantSlug || tenant.ownerUserId !== null ) { throw new Error(`Refusing to use tenant ${tenantSlug}: capacity harness metadata marker does not match`); } } async function ensureManagedTenant(client, tenantSlug) { await client.query('begin'); try { let tenant = await loadManagedTenant(client, tenantSlug); if (tenant) { assertManagedTenant(tenant, tenantSlug); } else { const inserted = await client.query( ` insert into public.tenants ( slug, name, legal_name, status, mode, billing_status, metadata ) values ( $1::citext, 'Capacity Test Students', 'Capacity Test Students - Non Production Only', 'active', 'saas', 'trial', jsonb_build_object( 'capacityHarness', jsonb_build_object( 'namespace', $2::text, 'managed', true, 'tenantSlug', $1::text ) ) ) returning id, slug::text as slug, name, owner_user_id as "ownerUserId", metadata `, [tenantSlug, CAPACITY_NAMESPACE], ); tenant = inserted.rows[0]; } await client.query('commit'); return tenant; } catch (error) { await client.query('rollback').catch(() => undefined); throw error; } } async function managedFixtureCounts(client, tenantId, tenantSlug) { const result = await client.query( ` with managed_users as ( select id from public.platform_users where raw_profile #>> '{capacityHarness,namespace}' = $1 and raw_profile #>> '{capacityHarness,tenantSlug}' = $2 and raw_profile #>> '{capacityHarness,tenantId}' = $3::text ) select (select count(*)::integer from managed_users) as "platformUsers", ( select count(*)::integer from public.tenant_memberships tm join managed_users u on u.id = tm.user_id where tm.tenant_id = $3::uuid and tm.role = 'student' ) as "tenantMemberships", ( select count(*)::integer from public.student_profiles sp join managed_users u on u.id = sp.user_id where sp.tenant_id = $3::uuid ) as "studentProfiles" `, [CAPACITY_NAMESPACE, tenantSlug, tenantId], ); return result.rows[0]; } async function assertManagedUsersAreIsolated(client, tenantId, tenantSlug) { const result = await client.query( ` select count(*) filter ( where u.auth_user_id is not null )::integer as "linkedAuthUsers", count(*) filter ( where coalesce(u.raw_profile #>> '{capacityHarness,tenantId}', '') <> $3::text )::integer as "wrongTenantMarkers", count(*) filter ( where exists ( select 1 from public.tenant_memberships tm where tm.user_id = u.id and tm.tenant_id <> $3::uuid ) )::integer as "crossTenantMemberships" from public.platform_users u where u.raw_profile #>> '{capacityHarness,namespace}' = $1 and u.raw_profile #>> '{capacityHarness,tenantSlug}' = $2 `, [CAPACITY_NAMESPACE, tenantSlug, tenantId], ); const isolation = result.rows[0]; if ( Number(isolation.linkedAuthUsers) > 0 || Number(isolation.wrongTenantMarkers) > 0 || Number(isolation.crossTenantMemberships) > 0 ) { throw new Error(`Refusing capacity fixture mutation: managed users are not isolated (${JSON.stringify(isolation)})`); } } async function assertManagedTenantMemberships(client, tenantId, tenantSlug) { const result = await client.query( ` select count(*)::integer as "unmanagedMemberships" from public.tenant_memberships tm join public.platform_users u on u.id = tm.user_id where tm.tenant_id = $3::uuid and ( tm.role <> 'student' or u.raw_profile #>> '{capacityHarness,namespace}' is distinct from $1 or u.raw_profile #>> '{capacityHarness,tenantSlug}' is distinct from $2 or u.raw_profile #>> '{capacityHarness,tenantId}' is distinct from $3::text ) `, [CAPACITY_NAMESPACE, tenantSlug, tenantId], ); if (Number(result.rows[0]?.unmanagedMemberships || 0) > 0) { throw new Error('Refusing capacity tenant operation: dedicated tenant contains unmanaged memberships'); } } async function assertBatchHasNoIdentityCollisions(client, tenantId, tenantSlug, start, end) { const result = await client.query( ` with source as ( select ordinal, $1::text || ':' || $2::text || ':' || lpad(ordinal::text, 6, '0') as legacy_id from generate_series($4::integer, $5::integer) ordinal ) select count(*)::integer as collisions from source join public.platform_users u on u.legacy_id = source.legacy_id where u.raw_profile #>> '{capacityHarness,namespace}' is distinct from $1 or u.raw_profile #>> '{capacityHarness,tenantSlug}' is distinct from $2 or u.raw_profile #>> '{capacityHarness,tenantId}' is distinct from $3::text `, [CAPACITY_NAMESPACE, tenantSlug, tenantId, start, end], ); if (Number(result.rows[0]?.collisions || 0) > 0) { throw new Error(`Refusing capacity fixture seed: legacy identity collision in ordinals ${start}-${end}`); } } async function seedBatch(client, tenantId, tenantSlug, start, end) { await client.query('begin'); try { await assertBatchHasNoIdentityCollisions(client, tenantId, tenantSlug, start, end); const result = await client.query( ` with source as materialized ( select ordinal, md5($1::text || ':' || $2::text || ':user:' || ordinal::text)::uuid as user_id, $1::text || ':' || $2::text || ':' || lpad(ordinal::text, 6, '0') as legacy_id, 'capacity_' || replace($2::text, '-', '_') || '_' || lpad(ordinal::text, 6, '0') as username, 'student' || lpad(ordinal::text, 6, '0') || '@' || $2::text || '.capacity.invalid' as email, '188' || lpad(ordinal::text, 8, '0') as phone, 'Capacity Student ' || lpad(ordinal::text, 6, '0') as name, timestamptz '2024-01-01 00:00:00+00' + (ordinal * interval '1 second') as created_at from generate_series($4::integer, $5::integer) ordinal ), upsert_users as ( insert into public.platform_users ( id, legacy_id, username, email, phone, name, primary_role, status, raw_profile, created_at, updated_at ) select source.user_id, source.legacy_id, source.username, source.email::citext, source.phone, source.name, 'student', 'active', jsonb_build_object( 'capacityHarness', jsonb_build_object( 'namespace', $1::text, 'managed', true, 'tenantSlug', $2::text, 'tenantId', $3::text, 'ordinal', source.ordinal ) ), source.created_at, now() from source on conflict (legacy_id) do update set username = excluded.username, email = excluded.email, phone = excluded.phone, name = excluded.name, primary_role = 'student', status = 'active', raw_profile = excluded.raw_profile, created_at = excluded.created_at, updated_at = now() where public.platform_users.raw_profile #>> '{capacityHarness,namespace}' = $1 and public.platform_users.raw_profile #>> '{capacityHarness,tenantSlug}' = $2 and public.platform_users.raw_profile #>> '{capacityHarness,tenantId}' = $3::text returning id ), upsert_memberships as ( insert into public.tenant_memberships ( tenant_id, user_id, role, status, permissions, created_at, updated_at ) select $3::uuid, source.user_id, 'student', 'active', '{}'::jsonb, source.created_at, now() from source join upsert_users users on users.id = source.user_id on conflict (tenant_id, user_id, role) do update set status = 'active', permissions = '{}'::jsonb, created_at = excluded.created_at, updated_at = now() returning id ), upsert_profiles as ( insert into public.student_profiles ( tenant_id, user_id, questions_answered_today, mastered_words_count, stats, progress, module_selections, recent_activities, created_at, updated_at ) select $3::uuid, source.user_id, source.ordinal % 80, source.ordinal % 5000, jsonb_build_object('capacityHarnessOrdinal', source.ordinal), jsonb_build_object('completionPercent', source.ordinal % 101), '{}'::jsonb, '[]'::jsonb, source.created_at, now() from source join upsert_users users on users.id = source.user_id on conflict (tenant_id, user_id) do update set questions_answered_today = excluded.questions_answered_today, mastered_words_count = excluded.mastered_words_count, stats = excluded.stats, progress = excluded.progress, module_selections = excluded.module_selections, recent_activities = excluded.recent_activities, created_at = excluded.created_at, updated_at = now() returning id ) select (select count(*)::integer from upsert_users) as users, (select count(*)::integer from upsert_memberships) as memberships, (select count(*)::integer from upsert_profiles) as profiles `, [CAPACITY_NAMESPACE, tenantSlug, tenantId, start, end], ); const expected = end - start + 1; const counts = result.rows[0]; for (const key of ['users', 'memberships', 'profiles']) { if (Number(counts?.[key] || 0) !== expected) { throw new Error(`capacity batch ${start}-${end} wrote ${counts?.[key] || 0} ${key}; expected ${expected}`); } } await client.query('commit'); return counts; } catch (error) { await client.query('rollback').catch(() => undefined); throw error; } } async function seedFixture(client, options) { const tenant = await ensureManagedTenant(client, options.tenantSlug); assertManagedTenant(tenant, options.tenantSlug); await assertManagedTenantMemberships(client, tenant.id, options.tenantSlug); await assertManagedUsersAreIsolated(client, tenant.id, options.tenantSlug); const before = await managedFixtureCounts(client, tenant.id, options.tenantSlug); if (Number(before.platformUsers) > options.count) { throw new Error( `managed fixture already has ${before.platformUsers} users; cleanup is required before reducing it to ${options.count}`, ); } const batches = []; for (let start = 1; start <= options.count; start += options.batchSize) { const end = Math.min(options.count, start + options.batchSize - 1); const counts = await seedBatch(client, tenant.id, options.tenantSlug, start, end); batches.push({ start, end, ...counts }); console.error(`[capacity] seeded ${end}/${options.count} students`); } await client.query('analyze public.platform_users'); await client.query('analyze public.tenant_memberships'); await client.query('analyze public.student_profiles'); const after = await managedFixtureCounts(client, tenant.id, options.tenantSlug); for (const key of ['platformUsers', 'tenantMemberships', 'studentProfiles']) { if (Number(after[key]) !== options.count) { throw new Error(`capacity fixture validation failed: ${key}=${after[key]}, expected ${options.count}`); } } return { tenant, before, after, batches }; } function buildStudentListQuery({ keyword = false, cursor = false, explain = false } = {}) { const params = { tenantId: 1, status: 2 }; let nextParam = 3; const filters = ['tm.tenant_id = $1', `tm.role = 'student'`, 'tm.status = $2']; if (keyword) { params.keyword = nextParam++; filters.push(`( coalesce(u.username, '') || ' ' || coalesce(u.name, '') || ' ' || coalesce(u.phone, '') || ' ' || coalesce(u.email::text, '') ) ilike $${params.keyword} escape '\\'`); } if (cursor) { params.cursorCreatedAt = nextParam++; params.cursorMembershipId = nextParam++; filters.push( `(tm.created_at, tm.id) < ($${params.cursorCreatedAt}::timestamptz, $${params.cursorMembershipId}::uuid)`, ); } params.limit = nextParam; const sql = ` with student_page as materialized ( select tm.id, tm.tenant_id, tm.user_id, tm.status, tm.created_at, tm.updated_at from public.tenant_memberships tm join public.platform_users u on u.id = tm.user_id left join public.student_profiles sp on sp.tenant_id = tm.tenant_id and sp.user_id = tm.user_id where ${filters.join(' and ')} order by tm.created_at desc, tm.id desc limit $${params.limit} ), class_agg as ( select tcm.tenant_id, tcm.user_id, jsonb_agg( jsonb_build_object( 'classId', tc.id, 'className', tc.name, 'classCode', tc.code, 'memberType', tcm.member_type, 'joinedAt', tcm.joined_at ) order by tc.sort_order asc, tc.created_at desc ) filter (where tcm.status = 'active') as classes from public.tenant_class_members tcm join student_page page on page.tenant_id = tcm.tenant_id and page.user_id = tcm.user_id join public.tenant_classes tc on tc.tenant_id = tcm.tenant_id and tc.id = tcm.class_id where tcm.tenant_id = $1 and tcm.member_type = 'student' group by tcm.tenant_id, tcm.user_id ) select tm.id as "membershipId", tm.user_id as "userId", tm.status, tm.created_at as "memberCreatedAt", tm.created_at::text as "cursorCreatedAt", tm.updated_at as "memberUpdatedAt", u.username, u.email::text as email, u.phone, u.name, null::text as "avatarUrl", u.primary_role as "primaryRole", u.last_seen_at as "lastSeenAt", sp.id as "profileId", sp.region_id as "regionId", r.name as "regionName", sp.selected_school_id as "selectedSchoolId", s.name as "selectedSchoolName", sp.selected_major_id as "selectedMajorId", m.name as "selectedMajorName", sp.questions_answered_today as "questionsAnsweredToday", sp.mastered_words_count as "masteredWordsCount", sp.last_check_in_date as "lastCheckInDate", sp.stats, sp.progress, sp.module_selections as "moduleSelections", coalesce(ca.classes, '[]'::jsonb) as classes from student_page tm join public.platform_users u on u.id = tm.user_id left join public.student_profiles sp on sp.tenant_id = tm.tenant_id and sp.user_id = tm.user_id left join public.regions r on r.tenant_id = tm.tenant_id and r.id = sp.region_id left join public.schools s on s.tenant_id = tm.tenant_id and s.id = sp.selected_school_id left join public.majors m on m.tenant_id = tm.tenant_id and m.id = sp.selected_major_id left join class_agg ca on ca.tenant_id = tm.tenant_id and ca.user_id = tm.user_id order by tm.created_at desc, tm.id desc `; return { sql: explain ? `explain (analyze, buffers, format json) ${sql}` : sql, params, }; } async function assertBenchmarkIndexes(client) { const names = [ 'idx_memberships_student_keyset_page', 'idx_platform_users_identity_search_trgm', ]; const result = await client.query( ` select index_name, to_regclass('public.' || index_name)::text as relation, pg_get_indexdef(to_regclass('public.' || index_name)) as definition from unnest($1::text[]) index_name order by index_name `, [names], ); const missing = result.rows.filter(row => !row.relation || !row.definition); if (missing.length) { throw new Error(`required student capacity indexes are missing: ${missing.map(row => row.index_name).join(', ')}`); } return result.rows.map(row => ({ name: row.index_name, definition: normalizePlanText(row.definition) })); } async function loadBenchmarkFixture(client, tenantSlug) { const tenant = await loadManagedTenant(client, tenantSlug); assertManagedTenant(tenant, tenantSlug); await assertManagedTenantMemberships(client, tenant.id, tenantSlug); await assertManagedUsersAreIsolated(client, tenant.id, tenantSlug); const counts = await managedFixtureCounts(client, tenant.id, tenantSlug); if ( Number(counts.platformUsers) < 10 || counts.platformUsers !== counts.tenantMemberships || counts.platformUsers !== counts.studentProfiles ) { throw new Error(`capacity fixture is incomplete: ${JSON.stringify(counts)}`); } return { tenant, counts, count: Number(counts.platformUsers) }; } async function loadBenchmarkTargets(client, tenantId, tenantSlug, count) { const searchOrdinal = Math.max(1, Math.floor(count / 2)); const deepOrdinal = Math.max(2, Math.floor(count * 0.1)); const result = await client.query( ` select u.legacy_id as "legacyId", u.name, u.phone, u.email::text as email, tm.id as "membershipId", tm.created_at as "createdAt" from public.platform_users u join public.tenant_memberships tm on tm.tenant_id = $1 and tm.user_id = u.id and tm.role = 'student' where u.legacy_id = any($2::text[]) `, [tenantId, [studentLegacyId(tenantSlug, searchOrdinal), studentLegacyId(tenantSlug, deepOrdinal)]], ); const byLegacyId = new Map(result.rows.map(row => [row.legacyId, row])); const search = byLegacyId.get(studentLegacyId(tenantSlug, searchOrdinal)); const deep = byLegacyId.get(studentLegacyId(tenantSlug, deepOrdinal)); if (!search || !deep) throw new Error('capacity benchmark target rows are missing'); return { searchOrdinal, deepOrdinal, approximateDeepCursorOffset: count - deepOrdinal, search, deep, }; } function explainSummary(document) { const root = Array.isArray(document) ? document[0] : document; const plan = root?.Plan || {}; const nodeTypes = new Set(); const indexes = new Set(); function visit(node) { if (!node || typeof node !== 'object') return; if (node['Node Type']) nodeTypes.add(node['Node Type']); if (node['Index Name']) indexes.add(node['Index Name']); for (const child of node.Plans || []) visit(child); } visit(plan); return { planningTimeMs: round(root?.['Planning Time']), executionTimeMs: round(root?.['Execution Time']), actualRows: Number(plan['Actual Rows'] || 0), nodeTypes: [...nodeTypes], indexes: [...indexes], buffers: { sharedHit: Number(plan['Shared Hit Blocks'] || 0), sharedRead: Number(plan['Shared Read Blocks'] || 0), sharedDirtied: Number(plan['Shared Dirtied Blocks'] || 0), sharedWritten: Number(plan['Shared Written Blocks'] || 0), localHit: Number(plan['Local Hit Blocks'] || 0), localRead: Number(plan['Local Read Blocks'] || 0), tempRead: Number(plan['Temp Read Blocks'] || 0), tempWritten: Number(plan['Temp Written Blocks'] || 0), }, }; } async function benchmarkCase(client, definition, options) { const query = buildStudentListQuery(definition.shape); for (let index = 0; index < options.warmupIterations; index += 1) { await client.query(query.sql, definition.values); } const latencies = []; const rowCounts = []; for (let index = 0; index < options.iterations; index += 1) { const startedAt = performance.now(); const result = await client.query(query.sql, definition.values); latencies.push(performance.now() - startedAt); rowCounts.push(result.rowCount); } const explainQuery = buildStudentListQuery({ ...definition.shape, explain: true }); const explainResult = await client.query(explainQuery.sql, definition.values); const explain = explainResult.rows[0]?.['QUERY PLAN']; return { id: definition.id, label: definition.label, searchField: definition.searchField || null, keyword: definition.keyword || null, cursor: definition.cursor || null, iterations: options.iterations, rows: { min: Math.min(...rowCounts), max: Math.max(...rowCounts), }, latencyMs: { min: round(Math.min(...latencies)), p50: round(percentile(latencies, 50)), p95: round(percentile(latencies, 95)), max: round(Math.max(...latencies)), }, explain: { summary: explainSummary(explain), document: explain, }, }; } async function benchmarkFixture(client, options, safety) { const fixture = await loadBenchmarkFixture(client, options.tenantSlug); const indexes = await assertBenchmarkIndexes(client); const targets = await loadBenchmarkTargets( client, fixture.tenant.id, options.tenantSlug, fixture.count, ); const limitValue = options.pageLimit + 1; const nameKeyword = String(targets.search.name || '').replace(/^Capacity /, ''); const phoneKeyword = String(targets.search.phone || '').slice(-7); const emailKeyword = String(targets.search.email || '').match(/\d{6}@/)?.[0] || String(targets.search.email || ''); const definitions = [ { id: 'first-page', label: 'Tenant student first page', shape: {}, values: [fixture.tenant.id, 'active', limitValue], }, { id: 'deep-cursor', label: 'Tenant student deep cursor page', shape: { cursor: true }, values: [fixture.tenant.id, 'active', targets.deep.createdAt, targets.deep.membershipId, limitValue], cursor: { approximateOffset: targets.approximateDeepCursorOffset, anchorOrdinal: targets.deepOrdinal, }, }, { id: 'name-substring', label: 'Student name substring search', searchField: 'name', keyword: nameKeyword, shape: { keyword: true }, values: [fixture.tenant.id, 'active', containsSearchPattern(nameKeyword), limitValue], }, { id: 'phone-substring', label: 'Student phone substring search', searchField: 'phone', keyword: phoneKeyword, shape: { keyword: true }, values: [fixture.tenant.id, 'active', containsSearchPattern(phoneKeyword), limitValue], }, { id: 'email-substring', label: 'Student email substring search', searchField: 'email', keyword: emailKeyword, shape: { keyword: true }, values: [fixture.tenant.id, 'active', containsSearchPattern(emailKeyword), limitValue], }, ]; const cases = []; for (const definition of definitions) { console.error(`[capacity] benchmarking ${definition.id}`); cases.push(await benchmarkCase(client, definition, options)); } return { schemaVersion: 1, kind: 'tenant-student-capacity', generatedAt: new Date().toISOString(), safety: { databaseEnvironment: safety.environment, databaseTarget: safety.target, namespace: CAPACITY_NAMESPACE, tenantSlug: options.tenantSlug, productionAllowed: false, }, fixture: { platformUsers: Number(fixture.counts.platformUsers), tenantMemberships: Number(fixture.counts.tenantMemberships), studentProfiles: Number(fixture.counts.studentProfiles), }, config: { iterations: options.iterations, warmupIterations: options.warmupIterations, pageLimit: options.pageLimit, rawQueryLimit: limitValue, deepCursorApproximateOffset: targets.approximateDeepCursorOffset, }, indexes, cases, limitations: [ 'Synthetic non-production data only.', 'Latency samples are warm-cache observations from the current test host, not a production SLA.', 'The harness validates the unscoped tenant-admin student list shape; class/region filters require separate workload evidence.', ], }; } function reportMarkdown(report) { const lines = [ '# Tenant Student Capacity Evidence', '', `Generated: ${report.generatedAt}`, '', `Database environment: \`${report.safety.databaseEnvironment}\``, '', `Dedicated tenant: \`${report.safety.tenantSlug}\``, '', `Managed rows: ${report.fixture.platformUsers} platform users / ${report.fixture.tenantMemberships} memberships / ${report.fixture.studentProfiles} profiles`, '', ...(report.timingsMs ? [ `Harness timings: ${Object.entries(report.timingsMs).map(([key, value]) => `${key}=${value}ms`).join(', ')}`, '', ] : []), '| Case | Rows | P50 ms | P95 ms | EXPLAIN ms | Shared hit/read | Plan indexes |', '| --- | ---: | ---: | ---: | ---: | ---: | --- |', ]; for (const item of report.cases) { const summary = item.explain.summary; lines.push( `| ${item.id} | ${item.rows.min}-${item.rows.max} | ${item.latencyMs.p50} | ${item.latencyMs.p95} | ${summary.executionTimeMs} | ${summary.buffers.sharedHit}/${summary.buffers.sharedRead} | ${summary.indexes.join(', ') || 'none'} |`, ); } lines.push('', '## Index Definitions', ''); for (const index of report.indexes) { lines.push(`### ${index.name}`, '', '```sql', index.definition, '```', ''); } lines.push( '## Interpretation Limits', '', ...report.limitations.map(item => `- ${item}`), '', 'The full JSON report contains PostgreSQL `EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON)` documents for every case.', '', ); return `${lines.join('\n')}\n`; } function fileTimestamp(date = new Date()) { return date.toISOString().replace(/[-:]/g, '').replace(/\.\d{3}Z$/, 'Z'); } async function writeReport(report, outputDir) { const absoluteOutputDir = path.resolve(outputDir); await fs.mkdir(absoluteOutputDir, { recursive: true }); const stamp = fileTimestamp(new Date(report.generatedAt)); const jsonPath = path.join(absoluteOutputDir, `tenant-student-capacity-${stamp}.json`); const markdownPath = path.join(absoluteOutputDir, `tenant-student-capacity-${stamp}.md`); await fs.writeFile(jsonPath, `${JSON.stringify(report, null, 2)}\n`, 'utf8'); await fs.writeFile(markdownPath, reportMarkdown(report), 'utf8'); return { jsonPath, markdownPath }; } async function cleanupManagedFixture(client, tenantSlug) { const tenant = await loadManagedTenant(client, tenantSlug); let tenantId = null; if (tenant) { assertManagedTenant(tenant, tenantSlug); tenantId = tenant.id; await assertManagedTenantMemberships(client, tenant.id, tenantSlug); await assertManagedUsersAreIsolated(client, tenant.id, tenantSlug); } else { const orphanSafety = await client.query( ` select count(*)::integer as unsafe from public.platform_users u where u.raw_profile #>> '{capacityHarness,namespace}' = $1 and u.raw_profile #>> '{capacityHarness,tenantSlug}' = $2 and ( u.auth_user_id is not null or exists (select 1 from public.tenant_memberships tm where tm.user_id = u.id) ) `, [CAPACITY_NAMESPACE, tenantSlug], ); if (Number(orphanSafety.rows[0]?.unsafe || 0) > 0) { throw new Error('Refusing orphan capacity cleanup: managed users still have auth or tenant membership references'); } } let deletedTenant = 0; if (tenantId) { const deleted = await client.query( ` delete from public.tenants where id = $1 and metadata #>> '{capacityHarness,namespace}' = $2 and metadata #>> '{capacityHarness,tenantSlug}' = $3 `, [tenantId, CAPACITY_NAMESPACE, tenantSlug], ); deletedTenant = deleted.rowCount; } let deletedUsers = 0; while (true) { const deleted = await client.query( ` with doomed as ( select id from public.platform_users where raw_profile #>> '{capacityHarness,namespace}' = $1 and raw_profile #>> '{capacityHarness,tenantSlug}' = $2 and auth_user_id is null and not exists ( select 1 from public.tenant_memberships tm where tm.user_id = public.platform_users.id ) order by id limit 5000 ) delete from public.platform_users users using doomed where users.id = doomed.id `, [CAPACITY_NAMESPACE, tenantSlug], ); deletedUsers += deleted.rowCount; if (deleted.rowCount === 0) break; } const remaining = await client.query( ` with managed_users as ( select id from public.platform_users where raw_profile #>> '{capacityHarness,namespace}' = $1 and raw_profile #>> '{capacityHarness,tenantSlug}' = $2 ) select ( select count(*)::integer from public.tenants where slug = $2::citext and metadata #>> '{capacityHarness,namespace}' = $1 and metadata #>> '{capacityHarness,tenantSlug}' = $2 ) as tenants, (select count(*)::integer from managed_users) as "platformUsers", ( select count(*)::integer from public.tenant_memberships membership join managed_users users on users.id = membership.user_id ) as memberships, ( select count(*)::integer from public.student_profiles profile join managed_users users on users.id = profile.user_id ) as profiles `, [CAPACITY_NAMESPACE, tenantSlug], ); const remainingCounts = remaining.rows[0] || {}; const cleanupVerified = Object.values(remainingCounts).every(value => Number(value || 0) === 0); if (!cleanupVerified) { throw new Error(`capacity cleanup left managed rows behind: ${JSON.stringify(remainingCounts)}`); } return { deletedTenant, deletedUsers, cleanupVerified, remaining: remainingCounts }; } async function runDatabaseMode(options) { const totalStartedAt = performance.now(); safeTarget(options.databaseUrl); const client = new Client({ connectionString: options.databaseUrl, application_name: 'tiku-tenant-student-capacity', }); await client.connect(); let locked = false; try { const safety = await assertDestructiveTestDatabase({ client, databaseUrl: options.databaseUrl, confirmation: options.confirmation, operation: `tenant student capacity ${options.mode}`, }); await client.query(`select set_config('lock_timeout', '5s', false)`); await client.query(`select set_config('statement_timeout', '300s', false)`); await acquireHarnessLock(client, options.tenantSlug); locked = true; if (options.mode === 'cleanup') { const cleanupStartedAt = performance.now(); const cleanup = await cleanupManagedFixture(client, options.tenantSlug); return { mode: options.mode, cleanup, safety, timingsMs: { cleanup: round(performance.now() - cleanupStartedAt), total: round(performance.now() - totalStartedAt), }, }; } let seed = null; let report = null; let reportPaths = null; let primaryError = null; const timingsMs = {}; try { if (['seed', 'run', 'evidence', 'smoke'].includes(options.mode)) { const seedStartedAt = performance.now(); seed = await seedFixture(client, options); timingsMs.seed = round(performance.now() - seedStartedAt); } if (['benchmark', 'run', 'evidence', 'smoke'].includes(options.mode)) { const benchmarkStartedAt = performance.now(); report = await benchmarkFixture(client, options, safety); timingsMs.benchmark = round(performance.now() - benchmarkStartedAt); report.timingsMs = { ...timingsMs }; if (options.mode !== 'evidence') reportPaths = await writeReport(report, options.outputDir); } } catch (error) { primaryError = error; } let cleanup = null; if (['smoke', 'evidence'].includes(options.mode)) { try { const cleanupStartedAt = performance.now(); cleanup = await cleanupManagedFixture(client, options.tenantSlug); timingsMs.cleanup = round(performance.now() - cleanupStartedAt); } catch (cleanupError) { if (primaryError) { primaryError.message += `; cleanup also failed: ${cleanupError.message}`; } else { primaryError = cleanupError; } } } if (primaryError) throw primaryError; if (report && options.mode === 'evidence') { report.cleanup = cleanup; report.timingsMs = { ...timingsMs, total: round(performance.now() - totalStartedAt), }; reportPaths = await writeReport(report, options.outputDir); } return { mode: options.mode, safety, seed: seed ? { tenantId: seed.tenant.id, counts: seed.after, batches: seed.batches.length } : null, report: report ? { fixture: report.fixture, paths: reportPaths } : null, cleanup, timingsMs: { ...timingsMs, total: round(performance.now() - totalStartedAt), }, }; } finally { if (locked) await releaseHarnessLock(client, options.tenantSlug).catch(() => undefined); await client.end().catch(() => undefined); } } export async function main(argv = process.argv.slice(2), env = process.env) { const options = parseCapacityOptions(argv, env); if (options.mode === 'plan') { console.log(JSON.stringify(capacityPlan(options), null, 2)); return; } const result = await runDatabaseMode(options); console.log(JSON.stringify(result, null, 2)); } const invokedPath = process.argv[1] ? pathToFileURL(path.resolve(process.argv[1])).href : ''; if (import.meta.url === invokedPath) { main().catch(error => { console.error(`[capacity] ${error.message}`); process.exitCode = 1; }); } export { buildStudentListQuery, capacityPlan, containsSearchPattern, reportMarkdown, safeTarget, studentLegacyId, };