-- 003_sessions.sql -- 用户会话表 + 心跳管理 + 离线检测 + pg_cron 调度 -- ============================================================ -- 1. 用户会话表(跟踪当前状态和心跳) -- ============================================================ CREATE TABLE IF NOT EXISTS user_sessions ( user_id VARCHAR(128) PRIMARY KEY, current_state VARCHAR(64) NOT NULL DEFAULT 'Offline', last_heartbeat BIGINT NOT NULL, last_state_change BIGINT NOT NULL, updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); -- ============================================================ -- 2. 离线检测函数:心跳超时 60s 的用户自动补一条 Offline 检查点 -- pg_cron 每 1 分钟执行一次 -- ============================================================ CREATE OR REPLACE FUNCTION detect_offline_users( timeout_secs BIGINT DEFAULT 60 ) RETURNS SETOF BIGINT AS $$ DECLARE r RECORD; now_ts BIGINT; BEGIN now_ts := EXTRACT(EPOCH FROM now())::BIGINT; FOR r IN SELECT user_id, last_heartbeat FROM user_sessions WHERE current_state != 'Offline' AND (now_ts - last_heartbeat) > timeout_secs LOOP -- 插入离线检查点(时间戳 = 最后心跳 + 超时时间) INSERT INTO checkpoints (user_id, state, timestamp) VALUES (r.user_id, 'Offline', r.last_heartbeat + timeout_secs); -- 更新会话状态 UPDATE user_sessions SET current_state = 'Offline', last_state_change = r.last_heartbeat + timeout_secs, updated_at = now() WHERE user_id = r.user_id; RETURN NEXT 1; END LOOP; END; $$ LANGUAGE plpgsql; -- ============================================================ -- 3. pg_cron 调度(需要超级用户手动执行一次) -- ============================================================ -- -- -- 安装扩展(仅需一次) -- CREATE EXTENSION IF NOT EXISTS pg_cron; -- -- -- 每 1 分钟检测离线用户 -- SELECT cron.schedule( -- 'detect-offline', -- '* * * * *', -- $$ SELECT detect_offline_users(60); $$ -- ); -- -- -- 查看状态 -- SELECT * FROM cron.job;