detached 3975fb4

refactor: Optimize message cache initialization and retrieval logic

- Simplify message cache initialization in server hooks
- Streamline message fetching for public and private chat rooms
- Improve cache usage and fallback mechanisms
- Remove redundant cache checks and add more focused logging
commit
3975fb4bb6c8993707c97bb0607b6c831a1f55d5
author
Kit · · 2025-02-14 14:30 UTC
parent
a665266
signature
SSH UnverifiedSHA256:H91DFuEG4jpk5edzLA4aUKkpv4zv9Q339ipRmkph6Tk The key is unknown
3 files · +44 -28
M src/hooks.server.ts +2 -0
@@ -5,6 +5,7 @@ import { initializeDatabase } from "$lib/db/db.server";
55 import db from "$lib/db/db.server";
66 import { handleRateLimit } from "$lib/api/rate-limiter";
77 import { users } from "$lib/db/schema";
8+import { initializeMessageCache } from "$lib/cache/initialize-cache";
89
910 async function setAllUsersOffline() {
1011 try {
@@ -24,6 +25,7 @@ console.debug("Initializing database on server start...");
2425 initializeDatabase()
2526 .then(async () => {
2627 await setAllUsersOffline();
28+ await initializeMessageCache();
2729 })
2830 .catch(error => {
2931 console.error('Failed to initialize database:', error);
@@ -5,6 +5,7 @@ import { initializeDatabase } from "$lib/db/db.server";
5 import db from "$lib/db/db.server";5 import db from "$lib/db/db.server";
6 import { handleRateLimit } from "$lib/api/rate-limiter";6 import { handleRateLimit } from "$lib/api/rate-limiter";
7 import { users } from "$lib/db/schema";7 import { users } from "$lib/db/schema";
8+import { initializeMessageCache } from "$lib/cache/initialize-cache";
8 9
9 async function setAllUsersOffline() {10 async function setAllUsersOffline() {
10 try {11 try {
@@ -24,6 +25,7 @@ console.debug("Initializing database on server start...");
24 initializeDatabase()25 initializeDatabase()
25 .then(async () => {26 .then(async () => {
26 await setAllUsersOffline();27 await setAllUsersOffline();
28+ await initializeMessageCache();
27 })29 })
28 .catch(error => {30 .catch(error => {
29 console.error('Failed to initialize database:', error);31 console.error('Failed to initialize database:', error);
A src/lib/cache/initialize-cache.ts +30 -0
@@ -0,0 +1,30 @@
1+import { messageCache } from '$lib/cache/message-cache';
2+import db from '$lib/db/db.server';
3+import { messages } from '$lib/db/schema';
4+import { desc } from 'drizzle-orm';
5+
6+let isCacheInitialized = false;
7+
8+export async function initializeMessageCache(): Promise<void> {
9+ if (isCacheInitialized) {
10+ console.debug('[Cache] Message cache already initialized.');
11+ return;
12+ }
13+ try {
14+ console.debug('[Cache] Initializing message cache with pre-population.');
15+ const fetchedMessages = await db.select()
16+ .from(messages)
17+ .orderBy(desc(messages.timestamp))
18+ .limit(500);
19+ // Reverse to get messages in chronological order
20+ await messageCache.initialize(fetchedMessages.reverse());
21+ isCacheInitialized = true;
22+ const stats = messageCache.getCacheStats();
23+ console.debug('[Cache] Message cache initialized successfully:', {
24+ roomCount: stats.roomCount,
25+ totalMessages: stats.totalMessages
26+ });
27+ } catch (error) {
28+ console.error('[Cache] Failed to initialize message cache:', error);
29+ }
30+} ⏎̸
@@ -0,0 +1,30 @@
1+import { messageCache } from '$lib/cache/message-cache';
2+import db from '$lib/db/db.server';
3+import { messages } from '$lib/db/schema';
4+import { desc } from 'drizzle-orm';
5+
6+let isCacheInitialized = false;
7+
8+export async function initializeMessageCache(): Promise<void> {
9+ if (isCacheInitialized) {
10+ console.debug('[Cache] Message cache already initialized.');
11+ return;
12+ }
13+ try {
14+ console.debug('[Cache] Initializing message cache with pre-population.');
15+ const fetchedMessages = await db.select()
16+ .from(messages)
17+ .orderBy(desc(messages.timestamp))
18+ .limit(500);
19+ // Reverse to get messages in chronological order
20+ await messageCache.initialize(fetchedMessages.reverse());
21+ isCacheInitialized = true;
22+ const stats = messageCache.getCacheStats();
23+ console.debug('[Cache] Message cache initialized successfully:', {
24+ roomCount: stats.roomCount,
25+ totalMessages: stats.totalMessages
26+ });
27+ } catch (error) {
28+ console.error('[Cache] Failed to initialize message cache:', error);
29+ }
30+} ⏎̸
M src/routes/api/chat/messages/+server.ts +12 -28
@@ -89,34 +89,23 @@ export async function GET({ request, locals }) {
8989 // Ensure default chat room exists
9090 await ensureDefaultChatRoom(db);
9191
92- // Initialize cache if needed
93- if (!isCacheInitialized) {
94- await initializeCache();
95- }
96-
97- console.log('[Chat] Fetching messages', {
98- isPublic,
99- fromCache: isCacheInitialized,
100- roomId
101- });
102-
10392 let fetchedMessages: Message[];
104- if (isCacheInitialized) {
105- // Get from cache
106- fetchedMessages = messageCache.getMessages(roomId, isPublic ? 10 : 50);
93+ if (isPublic) {
94+ if (!isCacheInitialized) {
95+ await initializeCache();
96+ }
97+ console.log('[Chat] Fetching public messages from cache', { roomId });
98+ fetchedMessages = messageCache.getMessages(roomId, 10);
10799 } else {
108- // Fallback to DB if cache initialization failed
100+ if (!locals.user) {
101+ throw error(401, 'Authentication required');
102+ }
103+ console.log('[Chat] Fetching messages from DB for instant chat', { roomId });
109104 const query = db.select()
110105 .from(messages)
111106 .where(eq(messages.chatRoomId, roomId))
112- .orderBy(desc(messages.timestamp));
113-
114- if (isPublic) {
115- query.limit(10);
116- } else {
117- query.limit(50);
118- }
119-
107+ .orderBy(desc(messages.timestamp))
108+ .limit(50);
120109 fetchedMessages = (await query).reverse();
121110 }
122111
@@ -245,11 +234,6 @@ export async function POST({ request, locals }: { request: Request, locals: App.
245234 timestamp: newMessage.timestamp
246235 });
247236
248- // Add to cache if initialized
249- if (isCacheInitialized) {
250- messageCache.addMessage(newMessage);
251- }
252-
253237 // Broadcast the new message via the unified SSE emitter
254238 sseEmitter.emit('sse', { type: 'chatMessage', data: newMessage });
255239
@@ -89,34 +89,23 @@ export async function GET({ request, locals }) {
89 // Ensure default chat room exists89 // Ensure default chat room exists
90 await ensureDefaultChatRoom(db);90 await ensureDefaultChatRoom(db);
91 91
92- // Initialize cache if needed
93- if (!isCacheInitialized) {
94- await initializeCache();
95- }
96-
97- console.log('[Chat] Fetching messages', {
98- isPublic,
99- fromCache: isCacheInitialized,
100- roomId
101- });
102-
103 let fetchedMessages: Message[];92 let fetchedMessages: Message[];
104- if (isCacheInitialized) {93+ if (isPublic) {
105- // Get from cache94+ if (!isCacheInitialized) {
106- fetchedMessages = messageCache.getMessages(roomId, isPublic ? 10 : 50);95+ await initializeCache();
96+ }
97+ console.log('[Chat] Fetching public messages from cache', { roomId });
98+ fetchedMessages = messageCache.getMessages(roomId, 10);
107 } else {99 } else {
108- // Fallback to DB if cache initialization failed100+ if (!locals.user) {
101+ throw error(401, 'Authentication required');
102+ }
103+ console.log('[Chat] Fetching messages from DB for instant chat', { roomId });
109 const query = db.select()104 const query = db.select()
110 .from(messages)105 .from(messages)
111 .where(eq(messages.chatRoomId, roomId))106 .where(eq(messages.chatRoomId, roomId))
112- .orderBy(desc(messages.timestamp));107+ .orderBy(desc(messages.timestamp))
113-108+ .limit(50);
114- if (isPublic) {
115- query.limit(10);
116- } else {
117- query.limit(50);
118- }
119-
120 fetchedMessages = (await query).reverse();109 fetchedMessages = (await query).reverse();
121 }110 }
122 111
@@ -245,11 +234,6 @@ export async function POST({ request, locals }: { request: Request, locals: App.
245 timestamp: newMessage.timestamp234 timestamp: newMessage.timestamp
246 });235 });
247 236
248- // Add to cache if initialized
249- if (isCacheInitialized) {
250- messageCache.addMessage(newMessage);
251- }
252-
253 // Broadcast the new message via the unified SSE emitter237 // Broadcast the new message via the unified SSE emitter
254 sseEmitter.emit('sse', { type: 'chatMessage', data: newMessage });238 sseEmitter.emit('sse', { type: 'chatMessage', data: newMessage });
255 239

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 3

Tags 8

↑↓ moveenter openesc close