remove timer based kvstore status stragedy, only sse based now

This commit is contained in:
Soph :3 2026-01-04 20:41:49 +02:00
parent e64910d895
commit f1539bdffa
2 changed files with 40 additions and 60 deletions

View file

@ -1,7 +1,7 @@
import type { Handle } from '@sveltejs/kit'; import type { Handle } from '@sveltejs/kit';
import * as auth from '$lib/server/auth'; import * as auth from '$lib/server/auth';
import { kvStore } from '$lib/server/db'; import { kvStore } from '$lib/server/db';
import { _sendToSubscribers } from './routes/api/updates/+server'; import { _isUserConnected, _sendToSubscribers } from './routes/api/updates/+server';
import { Status } from '$lib'; import { Status } from '$lib';
const handleAuth: Handle = async ({ event, resolve }) => { const handleAuth: Handle = async ({ event, resolve }) => {
@ -24,57 +24,6 @@ const handleAuth: Handle = async ({ event, resolve }) => {
event.locals.user = user; event.locals.user = user;
event.locals.session = session; event.locals.session = session;
if (event.locals.user) {
const id = event.locals.user.id;
const overwrite = event.locals.user.statusOverwrite as 1 | 2 | 3 | undefined;
const now = Date.now();
const lastActiveKey = `user-${id}-last-active`;
const stateKey = `user-${id}-state`;
const timerKey = `user-${id}-offline-timer`;
const lastActive = kvStore.get<number>(lastActiveKey) ?? 0;
const state = kvStore.get<1 | 2 | 3>(stateKey) ?? Status.OFFLINE;
// always update activity
kvStore.set(lastActiveKey, now);
if (overwrite !== Status.OFFLINE) {
const shouldSend = state === Status.OFFLINE && now - lastActive > 5000;
if (shouldSend) {
const outgoingStatus = overwrite === Status.DND ? Status.DND : Status.ONLINE;
_sendToSubscribers(id, {
type: 'status',
id,
status: outgoingStatus
});
kvStore.set(stateKey, outgoingStatus);
}
}
const existingTimer = kvStore.get<NodeJS.Timeout>(timerKey);
if (existingTimer) {
clearTimeout(existingTimer);
}
const offlineTimer = setTimeout(() => {
const last = kvStore.get<number>(lastActiveKey) ?? 0;
if (Date.now() - last >= 10_000) {
_sendToSubscribers(id, {
type: 'status',
id,
status: Status.OFFLINE
});
kvStore.set(stateKey, Status.OFFLINE);
kvStore.delete(timerKey);
}
}, 10_000);
kvStore.set(timerKey, offlineTimer + '');
}
return resolve(event); return resolve(event);
}; };

View file

@ -1,3 +1,6 @@
import { Status } from '$lib';
import { kvStore } from '$lib/server/db/index.js';
interface SubscribedTo { interface SubscribedTo {
subscribed: string[]; subscribed: string[];
userId: string; userId: string;
@ -5,35 +8,63 @@ interface SubscribedTo {
} }
export const _clients = new Map<string, SubscribedTo>(); export const _clients = new Map<string, SubscribedTo>();
export function _sendToSubscribers(userId: string, payload: unknown) { export function _sendToSubscribers(userId: string, payload: unknown) {
for (const client of _clients) { for (const [key, client] of _clients) {
if (client[1].subscribed.includes(userId)) { if (client.subscribed.includes(userId)) {
try { try {
client[1].controller.enqueue(`data: ${JSON.stringify(payload)}\n\n`); client.controller.enqueue(`data: ${JSON.stringify(payload)}\n\n`);
} catch { } catch {
_clients.delete(client[0]); _clients.delete(key);
} }
} }
} }
} }
export function _isUserConnected(userId: string): boolean {
for (const client of _clients.values()) {
if (client.userId === userId) return true;
}
return false;
}
export async function GET({ locals, request }) { export async function GET({ locals, request }) {
if (!locals.user) { if (!locals.user) {
return new Response('No authentication', { status: 401 }); return new Response('No authentication', { status: 401 });
} }
const subscribed = locals.user.friends.map((z) => z.id); const userId = locals.user.id;
//@TODO add more to subscribed eventually, server members, et cetera
const subscribed = locals.user.friends.map((f) => f.id);
const overwrite = locals.user.statusOverwrite;
const reqId = crypto.randomUUID(); const reqId = crypto.randomUUID();
const stream = new ReadableStream({ const stream = new ReadableStream({
start(controller) { start(controller) {
_clients.set(reqId, { subscribed, userId: locals.user!.id, controller }); _clients.set(reqId, { subscribed, userId, controller });
console.log(`SSE Client opened. ${_clients.size}`); console.log(`SSE Client opened. total: ${_clients.size}`);
controller.enqueue(`data: ${JSON.stringify({ type: 'connected' })}\n\n`); controller.enqueue(`data: ${JSON.stringify({ type: 'connected' })}\n\n`);
if (overwrite === Status.DND) {
kvStore.set(`user-${userId}-state`, Status.DND);
_sendToSubscribers(userId, { type: 'status', id: userId, status: Status.DND });
} else {
kvStore.set(`user-${userId}-state`, Status.ONLINE);
_sendToSubscribers(userId, { type: 'status', id: userId, status: Status.ONLINE });
}
request.signal.addEventListener('abort', () => { request.signal.addEventListener('abort', () => {
_clients.delete(reqId); _clients.delete(reqId);
console.log(`SSE Client aborted. ${_clients.size}`); console.log(`SSE Client aborted. total: ${_clients.size}`);
if (_isUserConnected(userId)) return;
if (overwrite === Status.OFFLINE) return;
kvStore.set(`user-${userId}-state`, Status.OFFLINE);
_sendToSubscribers(userId, { type: 'status', id: userId, status: Status.OFFLINE });
}); });
} }
}); });