拆分打手会话仓储

This commit is contained in:
yml2213
2026-08-21 17:53:17 +08:00
parent fa0cc7772c
commit 01bfb53011
3 changed files with 151 additions and 159 deletions
@@ -1,6 +1,7 @@
export * from './types.js'
export * from './shared.js'
export * from './worker-repo.js'
export * from './worker-session-repo.js'
export * from './work-order-repo.js'
export * from './work-order-event-repo.js'
export * from './work-order-share-repo.js'
@@ -8,7 +8,6 @@ import type {
WorkerFinanceRequestRow,
WorkerLevelRow,
WorkerUserRow,
WorkerSessionRow,
WorkerWithdrawalAccountRow,
WorkerWalletLedgerRow,
WorkerWalletRow,
@@ -58,164 +57,16 @@ const WORKER_FINANCE_REQUEST_SELECT = `
) withdraw_stats ON TRUE
`
export type CreateWorkerSessionInput = {
sessionId: string
workerId: number
deviceId: string
deviceType: string
deviceName: string
userAgent: string
ipAddress: string
issuedAt: string
expiresAt: string
now: string
maxDevices: number
}
export type CreateWorkerSessionResult = {
created: boolean
activeSessions: WorkerSessionRow[]
session: WorkerSessionRow | null
}
export async function createWorkerSessionRecord(
input: CreateWorkerSessionInput,
): Promise<CreateWorkerSessionResult> {
return withTransaction(async (client) => {
// 对账号加行锁,避免并发登录同时绕过设备数量限制。
await client.query('SELECT id FROM worker_users WHERE id = $1 FOR UPDATE', [input.workerId])
await client.query(
`
UPDATE worker_sessions
SET status = 'revoked', revoked_at = $2, updated_at = $2
WHERE worker_id = $1 AND status = 'active' AND expires_at <= $2
`,
[input.workerId, input.now],
)
await client.query(
`
UPDATE worker_sessions
SET status = 'revoked', revoked_at = $3, updated_at = $3
WHERE worker_id = $1 AND device_id = $2 AND status = 'active'
`,
[input.workerId, input.deviceId, input.now],
)
const activeResult = await client.query<WorkerSessionRow>(
`
SELECT * FROM worker_sessions
WHERE worker_id = $1 AND status = 'active' AND expires_at > $2
ORDER BY last_seen_at DESC, id DESC
`,
[input.workerId, input.now],
)
const activeSessions = activeResult.rows
if (activeSessions.length >= input.maxDevices) {
return { created: false, activeSessions, session: null }
}
const result = await client.query<WorkerSessionRow>(
`
INSERT INTO worker_sessions (
session_id, worker_id, device_id, device_type, device_name,
user_agent, ip_address, status, issued_at, last_seen_at,
expires_at, created_at, updated_at
) VALUES ($1, $2, $3, $4, $5, $6, $7, 'active', $8, $8, $9, $10, $10)
RETURNING *
`,
[
input.sessionId,
input.workerId,
input.deviceId,
input.deviceType,
input.deviceName,
input.userAgent,
input.ipAddress,
input.issuedAt,
input.expiresAt,
input.now,
],
)
return { created: true, activeSessions, session: result.rows[0] || null }
})
}
export async function getWorkerSessionBySessionId(
sessionId: string,
): Promise<WorkerSessionRow | null> {
const result = await query<WorkerSessionRow>(
'SELECT * FROM worker_sessions WHERE session_id = $1 LIMIT 1',
[String(sessionId || '').trim()],
)
return result.rows[0] || null
}
export async function touchWorkerSession(sessionId: string, now: string): Promise<boolean> {
const result = await query(
`
UPDATE worker_sessions
SET last_seen_at = $2, updated_at = $2
WHERE session_id = $1 AND status = 'active' AND expires_at > $2
`,
[String(sessionId || '').trim(), now],
)
return (result.rowCount || 0) > 0
}
export async function revokeWorkerSession(
workerId: number | string,
sessionId: string,
now: string,
): Promise<boolean> {
const result = await query(
`
UPDATE worker_sessions
SET status = 'revoked', revoked_at = $3, updated_at = $3
WHERE worker_id = $1 AND session_id = $2 AND status = 'active'
`,
[Number(workerId), String(sessionId || '').trim(), now],
)
return (result.rowCount || 0) > 0
}
export async function revokeAllWorkerSessions(
workerId: number | string,
now: string,
): Promise<number> {
const result = await query(
`
UPDATE worker_sessions
SET status = 'revoked', revoked_at = $2, updated_at = $2
WHERE worker_id = $1 AND status = 'active'
`,
[Number(workerId), now],
)
return result.rowCount || 0
}
export async function listWorkerSessions(
workerId: number | string,
now: string,
): Promise<WorkerSessionRow[]> {
await query(
`
UPDATE worker_sessions
SET status = 'revoked', revoked_at = $2, updated_at = $2
WHERE worker_id = $1 AND status = 'active' AND expires_at <= $2
`,
[Number(workerId), now],
)
const result = await query<WorkerSessionRow>(
`
SELECT * FROM worker_sessions
WHERE worker_id = $1 AND status = 'active' AND expires_at > $2
ORDER BY device_type ASC, last_seen_at DESC, id DESC
`,
[Number(workerId), now],
)
return result.rows
}
export {
createWorkerSessionRecord,
getWorkerSessionBySessionId,
listWorkerSessions,
revokeAllWorkerSessions,
revokeWorkerSession,
touchWorkerSession,
type CreateWorkerSessionInput,
type CreateWorkerSessionResult,
} from './worker-session-repo.js'
export async function getWorkerLevelByKey(levelKey: string): Promise<WorkerLevelRow | null> {
const result = await query<WorkerLevelRow>(
@@ -0,0 +1,140 @@
import { query, withTransaction } from '../../db/client.js'
import type { WorkerSessionRow } from './types.js'
export type CreateWorkerSessionInput = {
sessionId: string
workerId: number
deviceId: string
deviceType: string
deviceName: string
userAgent: string
ipAddress: string
issuedAt: string
expiresAt: string
now: string
maxDevices: number
}
export type CreateWorkerSessionResult = {
created: boolean
activeSessions: WorkerSessionRow[]
session: WorkerSessionRow | null
}
export async function createWorkerSessionRecord(
input: CreateWorkerSessionInput,
): Promise<CreateWorkerSessionResult> {
return withTransaction(async (client) => {
// 对账号加行锁,避免并发登录同时绕过设备数量限制。
await client.query('SELECT id FROM worker_users WHERE id = $1 FOR UPDATE', [input.workerId])
await client.query(
`UPDATE worker_sessions
SET status = 'revoked', revoked_at = $2, updated_at = $2
WHERE worker_id = $1 AND status = 'active' AND expires_at <= $2`,
[input.workerId, input.now],
)
await client.query(
`UPDATE worker_sessions
SET status = 'revoked', revoked_at = $3, updated_at = $3
WHERE worker_id = $1 AND device_id = $2 AND status = 'active'`,
[input.workerId, input.deviceId, input.now],
)
const activeResult = await client.query<WorkerSessionRow>(
`SELECT * FROM worker_sessions
WHERE worker_id = $1 AND status = 'active' AND expires_at > $2
ORDER BY last_seen_at DESC, id DESC`,
[input.workerId, input.now],
)
const activeSessions = activeResult.rows
if (activeSessions.length >= input.maxDevices) {
return { created: false, activeSessions, session: null }
}
const result = await client.query<WorkerSessionRow>(
`INSERT INTO worker_sessions (
session_id, worker_id, device_id, device_type, device_name,
user_agent, ip_address, status, issued_at, last_seen_at,
expires_at, created_at, updated_at
) VALUES ($1, $2, $3, $4, $5, $6, $7, 'active', $8, $8, $9, $10, $10)
RETURNING *`,
[
input.sessionId,
input.workerId,
input.deviceId,
input.deviceType,
input.deviceName,
input.userAgent,
input.ipAddress,
input.issuedAt,
input.expiresAt,
input.now,
],
)
return { created: true, activeSessions, session: result.rows[0] || null }
})
}
export async function getWorkerSessionBySessionId(
sessionId: string,
): Promise<WorkerSessionRow | null> {
const result = await query<WorkerSessionRow>(
'SELECT * FROM worker_sessions WHERE session_id = $1 LIMIT 1',
[String(sessionId || '').trim()],
)
return result.rows[0] || null
}
export async function touchWorkerSession(sessionId: string, now: string): Promise<boolean> {
const result = await query(
`UPDATE worker_sessions
SET last_seen_at = $2, updated_at = $2
WHERE session_id = $1 AND status = 'active' AND expires_at > $2`,
[String(sessionId || '').trim(), now],
)
return (result.rowCount || 0) > 0
}
export async function revokeWorkerSession(
workerId: number | string,
sessionId: string,
now: string,
): Promise<boolean> {
const result = await query(
`UPDATE worker_sessions
SET status = 'revoked', revoked_at = $3, updated_at = $3
WHERE worker_id = $1 AND session_id = $2 AND status = 'active'`,
[Number(workerId), String(sessionId || '').trim(), now],
)
return (result.rowCount || 0) > 0
}
export async function revokeAllWorkerSessions(
workerId: number | string,
now: string,
): Promise<number> {
const result = await query(
`UPDATE worker_sessions
SET status = 'revoked', revoked_at = $2, updated_at = $2
WHERE worker_id = $1 AND status = 'active'`,
[Number(workerId), now],
)
return result.rowCount || 0
}
export async function listWorkerSessions(
workerId: number | string,
now: string,
): Promise<WorkerSessionRow[]> {
await query(
`UPDATE worker_sessions
SET status = 'revoked', revoked_at = $2, updated_at = $2
WHERE worker_id = $1 AND status = 'active' AND expires_at <= $2`,
[Number(workerId), now],
)
const result = await query<WorkerSessionRow>(
`SELECT * FROM worker_sessions
WHERE worker_id = $1 AND status = 'active' AND expires_at > $2
ORDER BY device_type ASC, last_seen_at DESC, id DESC`,
[Number(workerId), now],
)
return result.rows
}