后端迁移会话存储模块

This commit is contained in:
yml
2026-05-21 15:28:32 +08:00
parent b86d7e8974
commit 3176880b2e
2 changed files with 68 additions and 15 deletions
@@ -1,5 +1,3 @@
// @ts-check
import crypto from 'node:crypto'
import fs from 'node:fs/promises'
import path from 'node:path'
@@ -14,9 +12,53 @@ import {
SESSION_TTL_MS,
} from './session-state.js'
const sessions = new Map()
type BrowserContextLike = {
close?: () => Promise<void>
}
export async function registerTencentBrowserSession({ loginType, browserContext, page }) {
export type TencentBrowserSession = Record<string, any> & {
sessionId: string
loginType: string
status: string
notice: string
createdAt: string
updatedAt: string
expiresAt: number
autoCloseAt: number
autoCloseTimer: ReturnType<typeof setTimeout> | null
sessionDir: string
browserContext?: BrowserContextLike | null
page?: unknown
browserContextClosed?: boolean
}
type RegisterSessionInput = {
loginType: string
browserContext: BrowserContextLike
page: unknown
}
type CloseSessionDependency = {
closeSession: (session: TencentBrowserSession, options: { markClosed: boolean }) => Promise<void>
}
type CloseSessionOptions = {
markClosed: boolean
persistSessionState: (session: TencentBrowserSession) => Promise<unknown>
closeBrowserIfIdle: () => Promise<unknown>
}
type PersistSessionStateOptions = {
buildSessionPayload: (session: TencentBrowserSession) => unknown
}
const sessions = new Map<string, TencentBrowserSession>()
export async function registerTencentBrowserSession({
loginType,
browserContext,
page,
}: RegisterSessionInput): Promise<TencentBrowserSession> {
const sessionId = createSessionId()
const sessionDir = path.join(DATA_ROOT, sessionId)
await fs.mkdir(sessionDir, { recursive: true })
@@ -49,11 +91,11 @@ export async function registerTencentBrowserSession({ loginType, browserContext,
return session
}
export function listActiveTencentBrowserSessions() {
export function listActiveTencentBrowserSessions(): TencentBrowserSession[] {
return [...sessions.values()]
}
export async function getRequiredSession(sessionId) {
export async function getRequiredSession(sessionId: unknown): Promise<TencentBrowserSession> {
const key = String(sessionId || '').trim()
if (!key) {
@@ -75,12 +117,12 @@ export async function getRequiredSession(sessionId) {
return session
}
export function applyInitialQrSessionState(session) {
export function applyInitialQrSessionState(session: TencentBrowserSession): void {
resetTencentSessionAutoClose(session)
Object.assign(session, resolveInitialQrSessionState(session.loginType))
}
export function armRedeemedSessionAutoClose(session, { closeSession }) {
export function armRedeemedSessionAutoClose(session: TencentBrowserSession, { closeSession }: CloseSessionDependency): void {
resetTencentSessionAutoClose(session)
const autoCloseAt = Date.now() + REDEEM_SUCCESS_AUTO_CLOSE_MS
@@ -93,7 +135,7 @@ export function armRedeemedSessionAutoClose(session, { closeSession }) {
}, REDEEM_SUCCESS_AUTO_CLOSE_MS)
}
export function resetTencentSessionAutoClose(session) {
export function resetTencentSessionAutoClose(session?: TencentBrowserSession | null): void {
if (session?.autoCloseTimer) {
clearTimeout(session.autoCloseTimer)
session.autoCloseTimer = null
@@ -104,20 +146,20 @@ export function resetTencentSessionAutoClose(session) {
}
}
export async function cleanupExpiredTencentBrowserSessions({ closeSession }) {
export async function cleanupExpiredTencentBrowserSessions({ closeSession }: CloseSessionDependency): Promise<void> {
const expired = listActiveTencentBrowserSessions().filter((session) => session.expiresAt <= Date.now())
await Promise.all(expired.map((session) => closeSession(session, { markClosed: false })))
}
export async function closeSession(
session,
session: TencentBrowserSession,
{
markClosed,
persistSessionState,
closeBrowserIfIdle,
},
) {
}: CloseSessionOptions,
): Promise<void> {
resetTencentSessionAutoClose(session)
sessions.delete(session.sessionId)
@@ -139,7 +181,10 @@ export async function closeSession(
await closeBrowserIfIdle()
}
export async function persistSessionState(session, { buildSessionPayload }) {
export async function persistSessionState(
session: TencentBrowserSession,
{ buildSessionPayload }: PersistSessionStateOptions,
): Promise<void> {
await fs.mkdir(session.sessionDir, { recursive: true })
await fs.writeFile(
path.join(session.sessionDir, 'session.json'),
@@ -148,7 +193,7 @@ export async function persistSessionState(session, { buildSessionPayload }) {
)
}
function createSessionId() {
function createSessionId(): string {
let sessionId = ''
do {
@@ -456,6 +456,14 @@
- `npm run typecheck`
- `npm run build`
- `npm test` 共 139 个用例通过
92. 腾讯浏览器会话内存 store 模块迁移到 `.ts`
- `src/services/session/session-service-store.ts`
93. 浏览器会话对象、注册入参、关闭依赖、自动关闭 timer、session 状态持久化 payload 已显式类型化
94. Docker 内验证通过:
- `src/services/session/session.test.js` 共 14 个用例通过
- `npm run typecheck`
- `npm run build`
- `npm test` 共 139 个用例通过
## 下一步建议