(api) use filesystem-based storage instead of memory storage for sessions

the implementation is incomplete, e.g. it misses pruning old sessions, this is more meant as proof-of-concept
this should reenable the usage of multiple workers
This commit is contained in:
Valentyne Stigloher 2025-03-17 13:00:33 +01:00
parent 40a57edaf9
commit c7910e938e
3 changed files with 21 additions and 38 deletions

View File

@ -112,7 +112,6 @@
"markdown-it-sub": "^2.0.0",
"markdown-it-sup": "^2.0.0",
"marked": "^0.7.0",
"memorystore": "^1.6.7",
"nuxt": "^3.16.0",
"path-to-regexp": "0.1.12",
"postcss-rtl": "^2.0.0",

32
pnpm-lock.yaml generated
View File

@ -297,9 +297,6 @@ importers:
marked:
specifier: ^0.7.0
version: 0.7.0
memorystore:
specifier: ^1.6.7
version: 1.6.7
nuxt:
specifier: ^3.16.0
version: 3.16.0(@parcel/watcher@2.5.1)(@types/node@20.16.5)(db0@0.3.1(sqlite3@5.1.7))(encoding@0.1.13)(eslint@9.22.0(jiti@2.4.2))(ioredis@5.6.0)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.35.0)(sass@1.32.12)(sqlite3@5.1.7)(terser@5.33.0)(typescript@5.7.2)(vite@6.2.2(@types/node@20.16.5)(jiti@2.4.2)(sass@1.32.12)(terser@5.33.0)(yaml@2.7.0))(vue-tsc@2.2.0(typescript@5.7.2))(yaml@2.7.0)
@ -5403,9 +5400,6 @@ packages:
lru-cache@10.4.3:
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
lru-cache@4.1.5:
resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==}
lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
@ -5503,10 +5497,6 @@ packages:
resolution: {integrity: sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==}
engines: {node: '>=6'}
memorystore@1.6.7:
resolution: {integrity: sha512-OZnmNY/NDrKohPQ+hxp0muBcBKrzKNtHr55DbqSx9hLsYVNnomSAMRAtI7R64t3gf3ID7tHQA7mG4oL3Hu9hdw==}
engines: {node: '>=0.10'}
meow@3.7.0:
resolution: {integrity: sha512-TNdwZs0skRlpPpCUK25StC4VH+tP5GgeY1HQOOGP+lQ2xtdkN2VtT/5tiX9k3IWpkBPV9b3LsAWXn4GGi/PrSA==}
engines: {node: '>=0.10.0'}
@ -6451,9 +6441,6 @@ packages:
proxy-from-env@1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
pseudomap@1.0.2:
resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==}
psl@1.9.0:
resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==}
@ -8098,9 +8085,6 @@ packages:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
yallist@2.1.2:
resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==}
yallist@3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
@ -14535,11 +14519,6 @@ snapshots:
lru-cache@10.4.3: {}
lru-cache@4.1.5:
dependencies:
pseudomap: 1.0.2
yallist: 2.1.2
lru-cache@5.1.1:
dependencies:
yallist: 3.1.1
@ -14651,13 +14630,6 @@ snapshots:
mimic-fn: 2.1.0
p-is-promise: 2.1.0
memorystore@1.6.7:
dependencies:
debug: 4.4.0(supports-color@9.4.0)
lru-cache: 4.1.5
transitivePeerDependencies:
- supports-color
meow@3.7.0:
dependencies:
camelcase-keys: 2.1.0
@ -15779,8 +15751,6 @@ snapshots:
proxy-from-env@1.1.0: {}
pseudomap@1.0.2: {}
psl@1.9.0: {}
pump@3.0.2:
@ -17658,8 +17628,6 @@ snapshots:
y18n@5.0.8: {}
yallist@2.1.2: {}
yallist@3.1.1: {}
yallist@4.0.0: {}

View File

@ -6,7 +6,6 @@ import session from 'express-session';
import grant from 'grant';
import { useBase } from 'h3';
import { defineExpressHandler, getH3Event } from 'h3-express';
import memorystore from 'memorystore';
import SQL from 'sql-template-strings';
import buildLocaleList from '../src/buildLocaleList.ts';
@ -43,7 +42,26 @@ import { config } from './social.ts';
import { closeAuditLogConnection } from '~/server/audit.ts';
import { getLocale } from '~/server/data.ts';
const MemoryStore = memorystore(session);
class StorageStore extends session.Store {
get(sid: string, callback: (err: unknown, session?: (session.SessionData | null)) => void): void {
useStorage('data').getItem<session.SessionData>(`session:${sid}`)
.then((session) => callback(null, session))
.catch((error) => callback(error));
}
set(sid: string, session: session.SessionData, callback?: (err?: unknown) => void): void {
// unwrap session to make it a primitive object (otherwise unstorage will reject serializing the object)
useStorage('data').setItem(`session:${sid}`, { ...session })
.then(() => callback?.())
.catch((error) => callback?.(error));
}
destroy(sid: string, callback?: (err?: unknown) => void): void {
useStorage('data').removeItem(`session:${sid}`)
.then(() => callback?.())
.catch((error) => callback?.(error));
}
}
const router = express.Router();
@ -52,9 +70,7 @@ router.use(session({
cookie: { ...longtimeCookieSetting, sameSite: undefined }, // somehow, sameSite=lax breaks sign-in with apple 🙄
resave: false,
saveUninitialized: false,
store: new MemoryStore({
checkPeriod: 86400000, // 24h
}),
store: new StorageStore(),
}));
export class LazyDatabase implements Database {