This commit is contained in:
2026-04-29 11:47:28 +08:00
parent 6b7978957a
commit d3e7baca99
25 changed files with 1523 additions and 0 deletions
+78
View File
@@ -0,0 +1,78 @@
import crypto from "node:crypto";
export type SessionBinding = {
conversationId: string;
sessionId: string;
lastUsedAt: number;
};
export type SessionContext = {
conversationId: string;
accessToken?: string;
projectId?: string;
};
export class SessionRegistry {
private readonly ttlMs: number;
private readonly bindings = new Map<string, SessionBinding>();
constructor(ttlSeconds: number) {
this.ttlMs = ttlSeconds * 1000;
}
upsert(context: SessionContext, sessionId: string): SessionBinding {
const binding: SessionBinding = {
conversationId: context.conversationId,
sessionId,
lastUsedAt: Date.now(),
};
this.bindings.set(this.makeKey(context), binding);
return binding;
}
get(context: SessionContext): SessionBinding | null {
const key = this.makeKey(context);
const binding = this.bindings.get(key);
if (!binding) {
return null;
}
if (Date.now() - binding.lastUsedAt > this.ttlMs) {
this.bindings.delete(key);
return null;
}
binding.lastUsedAt = Date.now();
return binding;
}
count(): number {
this.evictExpired();
return this.bindings.size;
}
evictExpired(): string[] {
const expired: string[] = [];
const now = Date.now();
for (const [key, binding] of this.bindings.entries()) {
if (now - binding.lastUsedAt > this.ttlMs) {
expired.push(binding.sessionId);
this.bindings.delete(key);
}
}
return expired;
}
private makeKey(context: SessionContext): string {
const digest = crypto
.createHash("sha256")
.update(
[
context.conversationId,
context.accessToken ?? "",
context.projectId ?? "",
].join("|"),
)
.digest("hex");
return digest;
}
}