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(); 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); } }