feat(server): add is_test_account + marks_as_test schema

New columns support separating soak-harness test traffic from real
user traffic in stats queries. Rebuilds leaderboard_overall matview
to include is_test_account so the fast path stays filterable.

Migration is idempotent via DO $$ / IF NOT EXISTS blocks inside
SCHEMA_SQL, which runs on every server startup — same mechanism
every existing post-v1 column migration uses.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
adlee-was-taken
2026-04-10 23:48:35 -04:00
parent e8051b256b
commit d16367582c

View File

@@ -95,6 +95,19 @@ BEGIN
WHERE table_name = 'users_v2' AND column_name = 'last_seen_at') THEN
ALTER TABLE users_v2 ADD COLUMN last_seen_at TIMESTAMPTZ;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_name = 'users_v2' AND column_name = 'is_test_account') THEN
ALTER TABLE users_v2 ADD COLUMN is_test_account BOOLEAN DEFAULT FALSE;
END IF;
END $$;
-- Add marks_as_test to invite_codes if not exists
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_name = 'invite_codes' AND column_name = 'marks_as_test') THEN
ALTER TABLE invite_codes ADD COLUMN marks_as_test BOOLEAN DEFAULT FALSE;
END IF;
END $$;
-- Admin audit log table
@@ -296,14 +309,14 @@ CREATE TABLE IF NOT EXISTS system_metrics (
);
-- Leaderboard materialized view (refreshed periodically)
-- Drop and recreate if missing rating column (v3.1.0 migration)
-- Drop and recreate if missing is_test_account column (soak harness migration)
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM pg_matviews WHERE matviewname = 'leaderboard_overall') THEN
-- Check if rating column exists in the view
-- Check if is_test_account column exists in the view
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'leaderboard_overall' AND column_name = 'rating'
WHERE table_name = 'leaderboard_overall' AND column_name = 'is_test_account'
) THEN
DROP MATERIALIZED VIEW leaderboard_overall;
END IF;
@@ -315,6 +328,7 @@ BEGIN
SELECT
u.id as user_id,
u.username,
COALESCE(u.is_test_account, FALSE) as is_test_account,
s.games_played,
s.games_won,
ROUND(s.games_won::numeric / NULLIF(s.games_played, 0) * 100, 1) as win_rate,
@@ -342,6 +356,8 @@ CREATE INDEX IF NOT EXISTS idx_users_reset ON users_v2(reset_token) WHERE reset_
CREATE INDEX IF NOT EXISTS idx_users_guest ON users_v2(guest_id) WHERE guest_id IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_users_active ON users_v2(is_active) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_users_banned ON users_v2(is_banned) WHERE is_banned = TRUE;
CREATE INDEX IF NOT EXISTS idx_users_test_account ON users_v2(is_test_account)
WHERE is_test_account = TRUE;
CREATE INDEX IF NOT EXISTS idx_sessions_user ON user_sessions(user_id);
CREATE INDEX IF NOT EXISTS idx_sessions_token ON user_sessions(token_hash);