(key: string)
| 307 | * machines see each other's writes. |
| 308 | */ |
| 309 | export async function getSession(key: string): Promise<SessionState> { |
| 310 | const ctx = requestCtx.getStore(); |
| 311 | if (ctx) { |
| 312 | const cached = ctx.sessions.get(key); |
| 313 | if (cached) return cached; |
| 314 | } |
| 315 | |
| 316 | let session: SessionState | undefined; |
| 317 | try { |
| 318 | const storedShape = await getStore().get<Record<string, unknown>>(SESSIONS_COLLECTION, key); |
| 319 | if (storedShape) session = deserializeSession(storedShape); |
| 320 | } catch (err) { |
| 321 | logger.warn({ err, key }, 'Failed to load session from store; creating fresh'); |
| 322 | } |
| 323 | if (!session) { |
| 324 | session = createSession(); |
| 325 | } |
| 326 | session.lastAccessedAt = new Date(); |
| 327 | |
| 328 | if (ctx) { |
| 329 | ctx.sessions.set(key, session); |
| 330 | // Snapshot the round-trip shape (serialize after deserialize) so any |
| 331 | // normalization done by (de)serialize doesn't register as a mutation. |
| 332 | // stableStringify drops lastAccessedAt so "touch-only" reads don't flush. |
| 333 | ctx.snapshots.set(key, stableStringify(serializeSession(session, key))); |
| 334 | } |
| 335 | return session; |
| 336 | } |
| 337 | |
| 338 | |
| 339 | const MAX_DOMAIN_LEN = 253; // RFC 1035 max hostname length |
no test coverage detected