Шаг A3 (из 1.6) плана production-готовности: - package.json: скрипт "test": "vitest run" - pr-check.yml: шаг Tests после type check - server/utils/userActivity.ts: try/catch в trackUserActivity — синхронная ошибка трекинга активности больше не срывает authenticateToken (ложный 403 на первом запросе пользователя за минуту) - tests/auto-transitions.test.ts: 3 устаревших теста обновлены под намеренное поведение (forward-only position, синк assignee, аудит вместо системного сообщения) 45/45 тестов зелёные, npm run check чисто.
42 lines
1.5 KiB
TypeScript
42 lines
1.5 KiB
TypeScript
import { db } from "../db";
|
|
import { users } from "@shared/schema";
|
|
import { eq } from "drizzle-orm";
|
|
|
|
// In-memory throttle to avoid writing last_activity_at on every authenticated request.
|
|
// Maps userId -> timestamp (ms) of the last DB update.
|
|
const lastActivityUpdate = new Map<number, number>();
|
|
|
|
const THROTTLE_MS = 60_000; // 1 minute
|
|
|
|
/**
|
|
* Updates users.last_activity_at for the given user, throttled to once per minute.
|
|
* Fire-and-forget: does not block the caller.
|
|
*/
|
|
export function trackUserActivity(userId: number): void {
|
|
const now = Date.now();
|
|
const lastUpdate = lastActivityUpdate.get(userId);
|
|
if (lastUpdate && now - lastUpdate < THROTTLE_MS) return;
|
|
|
|
lastActivityUpdate.set(userId, now);
|
|
|
|
// Run async without awaiting so the request is not delayed.
|
|
// Синхронные ошибки (например, недоступный пул соединений) тоже не должны
|
|
// срывать аутентификацию — трекинг активности некритичен.
|
|
try {
|
|
db.update(users)
|
|
.set({ lastActivityAt: new Date() })
|
|
.where(eq(users.id, userId))
|
|
.then(() => {
|
|
// No-op on success
|
|
})
|
|
.catch((err) => {
|
|
// Reset the throttle timestamp on error so the next request retries.
|
|
lastActivityUpdate.delete(userId);
|
|
console.error("[trackUserActivity] failed to update user activity:", err);
|
|
});
|
|
} catch (err) {
|
|
lastActivityUpdate.delete(userId);
|
|
console.error("[trackUserActivity] failed to update user activity:", err);
|
|
}
|
|
}
|