perf(server): optimize failedAuthAttempts LRU eviction to O(1)

This commit is contained in:
Koala
2026-06-03 11:44:06 +02:00
parent b51e66d824
commit a6be6b2670
4 changed files with 19 additions and 9 deletions
+7
View File
@@ -4,6 +4,13 @@ All notable changes to the KoalaSync browser extension and relay server.
--- ---
## [v2.0.6] — 2026-06-03
### Performance & Security Hardening
- Optimized failed authentication attempts cache eviction algorithm to $O(1)$ by exploiting Javascript `Map` insertion-order properties. This completely removes the previous array copying and sorting bottleneck, neutralizing a potential main-thread blocking DoS vector under heavy brute-force password traffic.
---
## [v2.0.5] — 2026-06-03 ## [v2.0.5] — 2026-06-03
### Security & Hardening ### Security & Hardening
+1 -1
View File
@@ -12,7 +12,7 @@
<a href="https://chromewebstore.google.com/detail/koalasync/obbnmkmlaaddodakcbdljknjpagklifc"><img src="https://img.shields.io/badge/Chrome-Download-blue?logo=googlechrome&logoColor=white" alt="Chrome Extension"></a> <a href="https://chromewebstore.google.com/detail/koalasync/obbnmkmlaaddodakcbdljknjpagklifc"><img src="https://img.shields.io/badge/Chrome-Download-blue?logo=googlechrome&logoColor=white" alt="Chrome Extension"></a>
</p> </p>
<p align="center"><a href="CHANGELOG.md"><b>New v2.0.5 Release!</b> — See what's changed</a></p> <p align="center"><a href="CHANGELOG.md"><b>New v2.0.6 Release!</b> — See what's changed</a></p>
<p align="center"><i>KoalaSync is a lightweight Browser Extension and Relay Server for synchronized video playback on almost any website with a video element—YouTube, Twitch, Netflix, Emby, Jellyfin, and beyond. Built with a focus on <b>Data Sovereignty</b> and <b>Performance</b>.</i></p> <p align="center"><i>KoalaSync is a lightweight Browser Extension and Relay Server for synchronized video playback on almost any website with a video element—YouTube, Twitch, Netflix, Emby, Jellyfin, and beyond. Built with a focus on <b>Data Sovereignty</b> and <b>Performance</b>.</i></p>
+10 -7
View File
@@ -149,17 +149,19 @@ function recordAuthFailure(ip, roomId) {
for (const [key, record] of failedAuthAttempts.entries()) { for (const [key, record] of failedAuthAttempts.entries()) {
if (now - record.lastAttempt > 15 * 60 * 1000) { if (now - record.lastAttempt > 15 * 60 * 1000) {
failedAuthAttempts.delete(key); failedAuthAttempts.delete(key);
} else {
break; // Since entries are insertion-ordered by time, all subsequent entries are newer
} }
} }
// 2. If still over 50k, perform LRU-style eviction on the oldest 10,000 entries // 2. If still over 50k, perform LRU-style eviction on the oldest 10,000 entries (first items in Map order)
if (failedAuthAttempts.size > 50000) { if (failedAuthAttempts.size > 50000) {
log('SECURITY', 'failedAuthAttempts size exceeded 50000. Performing LRU-style eviction.'); log('SECURITY', 'failedAuthAttempts size exceeded 50000. Performing insertion-order eviction.');
const sortedEntries = Array.from(failedAuthAttempts.entries()) for (const [key] of failedAuthAttempts.entries()) {
.sort((a, b) => a[1].lastAttempt - b[1].lastAttempt); if (failedAuthAttempts.size <= 40000) {
break;
for (let i = 0; i < 10000 && i < sortedEntries.length; i++) { }
failedAuthAttempts.delete(sortedEntries[i][0]); failedAuthAttempts.delete(key);
} }
} }
} }
@@ -167,6 +169,7 @@ function recordAuthFailure(ip, roomId) {
const record = failedAuthAttempts.get(key) || { count: 0, lastAttempt: 0 }; const record = failedAuthAttempts.get(key) || { count: 0, lastAttempt: 0 };
record.count++; record.count++;
record.lastAttempt = Date.now(); record.lastAttempt = Date.now();
failedAuthAttempts.delete(key); // Remove first to update insertion order (moves key to the end of iteration)
failedAuthAttempts.set(key, record); failedAuthAttempts.set(key, record);
} }
+1 -1
View File
@@ -1,4 +1,4 @@
{ {
"version": "2.0.5", "version": "2.0.5",
"date": "2026-06-03T09:32:00Z" "date": "2026-06-03T09:34:22Z"
} }