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:
@@ -95,6 +95,19 @@ BEGIN
|
|||||||
WHERE table_name = 'users_v2' AND column_name = 'last_seen_at') THEN
|
WHERE table_name = 'users_v2' AND column_name = 'last_seen_at') THEN
|
||||||
ALTER TABLE users_v2 ADD COLUMN last_seen_at TIMESTAMPTZ;
|
ALTER TABLE users_v2 ADD COLUMN last_seen_at TIMESTAMPTZ;
|
||||||
END IF;
|
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 $$;
|
END $$;
|
||||||
|
|
||||||
-- Admin audit log table
|
-- Admin audit log table
|
||||||
@@ -296,14 +309,14 @@ CREATE TABLE IF NOT EXISTS system_metrics (
|
|||||||
);
|
);
|
||||||
|
|
||||||
-- Leaderboard materialized view (refreshed periodically)
|
-- 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 $$
|
DO $$
|
||||||
BEGIN
|
BEGIN
|
||||||
IF EXISTS (SELECT 1 FROM pg_matviews WHERE matviewname = 'leaderboard_overall') THEN
|
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 (
|
IF NOT EXISTS (
|
||||||
SELECT 1 FROM information_schema.columns
|
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
|
) THEN
|
||||||
DROP MATERIALIZED VIEW leaderboard_overall;
|
DROP MATERIALIZED VIEW leaderboard_overall;
|
||||||
END IF;
|
END IF;
|
||||||
@@ -315,6 +328,7 @@ BEGIN
|
|||||||
SELECT
|
SELECT
|
||||||
u.id as user_id,
|
u.id as user_id,
|
||||||
u.username,
|
u.username,
|
||||||
|
COALESCE(u.is_test_account, FALSE) as is_test_account,
|
||||||
s.games_played,
|
s.games_played,
|
||||||
s.games_won,
|
s.games_won,
|
||||||
ROUND(s.games_won::numeric / NULLIF(s.games_played, 0) * 100, 1) as win_rate,
|
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_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_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_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_user ON user_sessions(user_id);
|
||||||
CREATE INDEX IF NOT EXISTS idx_sessions_token ON user_sessions(token_hash);
|
CREATE INDEX IF NOT EXISTS idx_sessions_token ON user_sessions(token_hash);
|
||||||
|
|||||||
Reference in New Issue
Block a user