同步异常兜底
This commit is contained in:
1 parent
9cb8552a99
commit
a1b4a63552
20 files changed
+754
-54
No files matched your search
@@ -0,0 +1,64 @@
|
||||
interface JobCancellationState {
|
||||
requested: Set<string>
|
||||
controllers: Map<string, AbortController>
|
||||
}
|
||||
|
||||
const CANCELLED_CODE = 'JOB_CANCELLED'
|
||||
|
||||
const state = (globalThis as typeof globalThis & {
|
||||
__pichostJobCancellationState?: JobCancellationState
|
||||
}).__pichostJobCancellationState ?? {
|
||||
requested: new Set<string>(),
|
||||
controllers: new Map<string, AbortController>()
|
||||
}
|
||||
;(globalThis as typeof globalThis & {
|
||||
__pichostJobCancellationState?: JobCancellationState
|
||||
}).__pichostJobCancellationState = state
|
||||
|
||||
export function createJobCancelledError(): Error {
|
||||
const error = new Error('任务已取消')
|
||||
error.name = CANCELLED_CODE
|
||||
return error
|
||||
}
|
||||
|
||||
export function isJobCancelledError(error: unknown): boolean {
|
||||
return error instanceof Error && error.name === CANCELLED_CODE
|
||||
}
|
||||
|
||||
export function beginJobCancellationScope(jobId: string): void {
|
||||
state.requested.delete(jobId)
|
||||
state.controllers.get(jobId)?.abort()
|
||||
state.controllers.set(jobId, new AbortController())
|
||||
}
|
||||
|
||||
export function endJobCancellationScope(jobId: string): void {
|
||||
state.controllers.delete(jobId)
|
||||
state.requested.delete(jobId)
|
||||
}
|
||||
|
||||
export function requestJobCancellation(jobId: string): void {
|
||||
state.requested.add(jobId)
|
||||
state.controllers.get(jobId)?.abort(createJobCancelledError())
|
||||
}
|
||||
|
||||
export function isJobCancellationRequested(jobId: string): boolean {
|
||||
return state.requested.has(jobId)
|
||||
}
|
||||
|
||||
export function getJobAbortSignal(jobId: string): AbortSignal {
|
||||
return state.controllers.get(jobId)?.signal ?? new AbortController().signal
|
||||
}
|
||||
|
||||
export function getJobOperationSignal(
|
||||
jobId: string,
|
||||
timeoutMs: number
|
||||
): AbortSignal {
|
||||
return AbortSignal.any([
|
||||
getJobAbortSignal(jobId),
|
||||
AbortSignal.timeout(timeoutMs)
|
||||
])
|
||||
}
|
||||
|
||||
export function throwIfJobCancellationRequested(jobId: string): void {
|
||||
if (isJobCancellationRequested(jobId)) throw createJobCancelledError()
|
||||
}
|
||||
@@ -10,6 +10,11 @@ import {
|
||||
recoverInterruptedBackupJobs,
|
||||
type BackupJob
|
||||
} from './jobs'
|
||||
import {
|
||||
beginJobCancellationScope,
|
||||
endJobCancellationScope,
|
||||
requestJobCancellation
|
||||
} from './cancel-state'
|
||||
|
||||
interface BackupRunnerState {
|
||||
running: boolean
|
||||
@@ -42,11 +47,8 @@ export function cancelBackupJob(jobId: string): boolean {
|
||||
if (!job || (job.status !== 'running' && job.status !== 'pending')) {
|
||||
return false
|
||||
}
|
||||
markJobFailed(jobId, '任务已取消')
|
||||
if (runnerState.currentJobId === jobId) {
|
||||
runnerState.running = false
|
||||
runnerState.currentJobId = null
|
||||
}
|
||||
requestJobCancellation(jobId)
|
||||
markJobFailed(jobId, '任务已取消', '已请求取消,正在停止…')
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -59,14 +61,18 @@ export function scheduleBackupJob(
|
||||
}
|
||||
runnerState.running = true
|
||||
runnerState.currentJobId = job.id
|
||||
beginJobCancellationScope(job.id)
|
||||
markJobRunning(job.id)
|
||||
|
||||
setImmediate(() => {
|
||||
runner()
|
||||
.catch(() => {})
|
||||
.finally(() => {
|
||||
runnerState.running = false
|
||||
runnerState.currentJobId = null
|
||||
endJobCancellationScope(job.id)
|
||||
if (runnerState.currentJobId === job.id) {
|
||||
runnerState.running = false
|
||||
runnerState.currentJobId = null
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user