Cache grandfathered emails in memory at startup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lawrence Hook
2026-02-22 05:01:00 -05:00
parent afed16a38a
commit 56b119ed98
4 changed files with 16 additions and 4 deletions
+1
View File
@@ -135,6 +135,7 @@ function start() {
setInterval(runCleanup, CLEANUP_INTERVAL_MS);
// Start listening
storage.loadGrandfatheredEmails();
const grandfathered = storage.readGrandfatheredEmails();
console.log(`Loaded ${grandfathered.size} grandfathered emails`);
+11 -2
View File
@@ -28,7 +28,9 @@ function ensureDirectories() {
// Initialize on load
ensureDirectories();
// --- Grandfathered Emails (file-backed, no in-memory cache) ---
// --- Grandfathered Emails (loaded once at startup) ---
let grandfatheredSet = null;
function readGrandfatheredEmails() {
try {
@@ -43,8 +45,14 @@ function readGrandfatheredEmails() {
return new Set();
}
function loadGrandfatheredEmails() {
grandfatheredSet = readGrandfatheredEmails();
return grandfatheredSet;
}
function isGrandfathered(email) {
return readGrandfatheredEmails().has(email.toLowerCase());
if (!grandfatheredSet) loadGrandfatheredEmails();
return grandfatheredSet.has(email.toLowerCase());
}
// --- Subscription Cache (email -> premium status, file-backed, no in-memory cache) ---
@@ -277,6 +285,7 @@ function pruneExpiredRateLimits() {
module.exports = {
// Grandfathered
readGrandfatheredEmails,
loadGrandfatheredEmails,
isGrandfathered,
// Auth requests
+2 -2
View File
@@ -96,7 +96,7 @@ describe('License Routes', () => {
// Set up grandfathered file
const grandfatheredFile = path.join(testDataDir, config.GRANDFATHERED_FILE);
fs.writeFileSync(grandfatheredFile, 'donor@example.com\n');
storage.loadGrandfatheredEmails();
const token = generateSessionToken('donor@example.com');
@@ -116,7 +116,7 @@ describe('License Routes', () => {
it('should handle grandfathered check case-insensitively', async () => {
const grandfatheredFile = path.join(testDataDir, config.GRANDFATHERED_FILE);
fs.writeFileSync(grandfatheredFile, 'Donor@Example.com\n');
storage.loadGrandfatheredEmails();
// Token with lowercase email
const token = generateSessionToken('donor@example.com');
+2
View File
@@ -134,6 +134,7 @@ describe('Storage', () => {
it('should read grandfathered emails from file', () => {
const grandfatheredFile = path.join(testDataDir, config.GRANDFATHERED_FILE);
fs.writeFileSync(grandfatheredFile, 'donor1@example.com\nDonor2@Example.com\n');
storage.loadGrandfatheredEmails();
assert.strictEqual(storage.isGrandfathered('donor1@example.com'), true);
assert.strictEqual(storage.isGrandfathered('DONOR1@EXAMPLE.COM'), true);
@@ -142,6 +143,7 @@ describe('Storage', () => {
});
it('should handle missing grandfathered file gracefully', () => {
storage.loadGrandfatheredEmails();
// File doesn't exist, should not throw
assert.strictEqual(storage.isGrandfathered('anyone@example.com'), false);
});