mirror of
https://github.com/kennethnym/aris.git
synced 2026-03-20 09:01:19 +00:00
fix(backend): handle remove() during in-flight session creation
Cancel pending getOrCreate when remove() is called mid-flight. Destroy the resulting session to prevent it from leaking. Co-authored-by: Ona <no-reply@ona.com>
This commit is contained in:
@@ -225,4 +225,35 @@ describe("UserSessionManager", () => {
|
|||||||
expect(session1).toBe(session2)
|
expect(session1).toBe(session2)
|
||||||
expect(callCount).toBe(1)
|
expect(callCount).toBe(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("remove during in-flight getOrCreate prevents session from being stored", async () => {
|
||||||
|
let resolveProvider: () => void
|
||||||
|
const providerGate = new Promise<void>((r) => {
|
||||||
|
resolveProvider = r
|
||||||
|
})
|
||||||
|
|
||||||
|
const manager = new UserSessionManager({
|
||||||
|
providers: [
|
||||||
|
async () => {
|
||||||
|
await providerGate
|
||||||
|
return new LocationSource()
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const sessionPromise = manager.getOrCreate("user-1")
|
||||||
|
|
||||||
|
// remove() while provider is still resolving
|
||||||
|
manager.remove("user-1")
|
||||||
|
|
||||||
|
// Let the provider finish
|
||||||
|
resolveProvider!()
|
||||||
|
|
||||||
|
await expect(sessionPromise).rejects.toThrow("removed during creation")
|
||||||
|
|
||||||
|
// A fresh getOrCreate should produce a new session, not the cancelled one
|
||||||
|
const freshSession = await manager.getOrCreate("user-1")
|
||||||
|
expect(freshSession).toBeDefined()
|
||||||
|
expect(freshSession.engine).toBeDefined()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -32,6 +32,12 @@ export class UserSessionManager {
|
|||||||
this.pending.set(userId, promise)
|
this.pending.set(userId, promise)
|
||||||
try {
|
try {
|
||||||
const session = await promise
|
const session = await promise
|
||||||
|
// If remove() was called while we were awaiting, it clears the
|
||||||
|
// pending entry. Detect that and destroy the session immediately.
|
||||||
|
if (!this.pending.has(userId)) {
|
||||||
|
session.destroy()
|
||||||
|
throw new Error(`Session for user ${userId} was removed during creation`)
|
||||||
|
}
|
||||||
this.sessions.set(userId, session)
|
this.sessions.set(userId, session)
|
||||||
return session
|
return session
|
||||||
} finally {
|
} finally {
|
||||||
@@ -45,6 +51,8 @@ export class UserSessionManager {
|
|||||||
session.destroy()
|
session.destroy()
|
||||||
this.sessions.delete(userId)
|
this.sessions.delete(userId)
|
||||||
}
|
}
|
||||||
|
// Cancel any in-flight creation so getOrCreate won't store the session
|
||||||
|
this.pending.delete(userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createSession(userId: string): Promise<UserSession> {
|
private async createSession(userId: string): Promise<UserSession> {
|
||||||
|
|||||||
Reference in New Issue
Block a user