tangled
alpha
login
or
join now
dunkirk.sh
/
cachet
0
fork
atom
a cache for slack profile pictures and emojis
0
fork
atom
overview
issues
pulls
pipelines
feat: move the touch to refresh to non blocking
dunkirk.sh
1 month ago
85f77fdc
5234f52f
verified
This commit was signed with the committer's
known signature
.
dunkirk.sh
SSH Key Fingerprint:
SHA256:DqcG0RXYExE26KiWo3VxJnsxswN1QNfTBvB+bdSpk80=
+39
-7
1 changed file
expand all
collapse all
unified
split
src
cache.ts
+39
-7
src/cache.ts
···
348
348
private slackWrapper?: SlackUserProvider; // Will be injected after construction
349
349
private currentSessionId?: number;
350
350
351
351
+
// Touch-refresh queue for async non-blocking updates
352
352
+
private touchRefreshQueue: Array<{
353
353
+
newExpiration: number;
354
354
+
normalizedId: string;
355
355
+
}> = [];
356
356
+
private isFlushingTouchRefresh = false;
357
357
+
351
358
// Prepared statements for hot paths
352
359
private stmtTraffic10min!: Statement;
353
360
private stmtTrafficHourly!: Statement;
···
382
389
this.initPreparedStatements();
383
390
this.setupPurgeSchedule();
384
391
this.startQueueProcessor();
392
392
+
this.startTouchRefreshFlush();
385
393
386
394
// Run migrations
387
395
this.runMigrations();
···
987
995
}
988
996
989
997
/**
998
998
+
* Starts the touch-refresh flush timer (no-op, using microtasks instead)
999
999
+
* @private
1000
1000
+
*/
1001
1001
+
private startTouchRefreshFlush() {
1002
1002
+
// No timer needed - using queueMicrotask for immediate async execution
1003
1003
+
}
1004
1004
+
1005
1005
+
/**
1006
1006
+
* Flushes a single touch-refresh update asynchronously using microtask
1007
1007
+
* @private
1008
1008
+
*/
1009
1009
+
private flushTouchRefresh(newExpiration: number, normalizedId: string) {
1010
1010
+
queueMicrotask(() => {
1011
1011
+
try {
1012
1012
+
this.db.run("UPDATE users SET expiration = ? WHERE userId = ?", [
1013
1013
+
newExpiration,
1014
1014
+
normalizedId,
1015
1015
+
]);
1016
1016
+
} catch (error) {
1017
1017
+
console.error("Error in touch-refresh update:", error);
1018
1018
+
}
1019
1019
+
});
1020
1020
+
}
1021
1021
+
1022
1022
+
/**
990
1023
* Processes the user update queue with rate limiting
991
1024
* @private
992
1025
*/
···
1188
1221
if (userAge < twentyFourHoursAgo) {
1189
1222
// Extend TTL by another 7 days from now
1190
1223
const newExpiration = now + 7 * 24 * 60 * 60 * 1000;
1191
1191
-
this.db.run("UPDATE users SET expiration = ? WHERE userId = ?", [
1192
1192
-
newExpiration,
1193
1193
-
normalizedId,
1194
1194
-
]);
1224
1224
+
1225
1225
+
// Flush the UPDATE asynchronously using microtask (non-blocking)
1226
1226
+
this.flushTouchRefresh(newExpiration, normalizedId);
1195
1227
1196
1228
// Queue for background update to get fresh data
1197
1229
this.queueUserUpdate(normalizedId);
···
1281
1313
const respTime = responseTime || 0;
1282
1314
const nowMs = Date.now();
1283
1315
1284
1284
-
// Parse referer host outside transaction
1316
1316
+
// Parse referer host
1285
1317
let refererHost: string | null = null;
1286
1318
if (referer) {
1287
1319
try {
···
1291
1323
}
1292
1324
}
1293
1325
1294
1294
-
// Use prepared statements without transaction wrapper for lower latency
1295
1295
-
// WAL mode allows concurrent writes, and prepared statements are pre-compiled
1326
1326
+
// Use prepared statements - these are FAST with WAL mode
1327
1327
+
// WAL allows concurrent reads during these writes
1296
1328
this.stmtTraffic10min.run(bucket10min, endpoint, statusCode, respTime);
1297
1329
this.stmtTrafficHourly.run(bucketHour, endpoint, statusCode, respTime);
1298
1330
this.stmtTrafficDaily.run(bucketDay, endpoint, statusCode, respTime);