mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
115 lines
4.6 KiB
TypeScript
115 lines
4.6 KiB
TypeScript
//#region src/core/tasks/task.d.ts
|
|
/** Recursively marks all properties as readonly. */
|
|
type DeepReadonly<T> = T extends (infer U)[] ? ReadonlyArray<DeepReadonly<U>> : T extends object ? { readonly [K in keyof T]: DeepReadonly<T[K]>; } : T;
|
|
type TaskStatus = 'pending' | 'running' | 'done' | 'error';
|
|
/**
|
|
* Configuration for a Task.
|
|
*/
|
|
interface TaskConfig {
|
|
/**
|
|
* Identifier for this task.
|
|
* - string: used as-is
|
|
* - () => string: called once at construction time
|
|
* - undefined: a unique ID is generated via generateId()
|
|
*/
|
|
id?: string | (() => string);
|
|
/**
|
|
* Optional external AbortSignal to compose with the task's internal one.
|
|
* The task's work is aborted when either the internal controller (via abort())
|
|
* or this external signal fires — whichever comes first.
|
|
*/
|
|
signal?: AbortSignal;
|
|
}
|
|
/**
|
|
* Minimal contract for a schedulable unit of async work.
|
|
*/
|
|
interface TaskLike<TValue = void, TError = unknown> {
|
|
readonly id: string;
|
|
readonly status: TaskStatus;
|
|
readonly value: DeepReadonly<TValue> | undefined;
|
|
readonly error: DeepReadonly<TError> | undefined;
|
|
run(): Promise<TValue>;
|
|
abort(): void;
|
|
}
|
|
/**
|
|
* Generic reusable task that wraps an async run function.
|
|
*
|
|
* Owns its own AbortController so it can always be aborted independently.
|
|
* Optionally composes an external AbortSignal so that a parent's cancellation
|
|
* propagates into the task's work without requiring the caller to track the
|
|
* task separately.
|
|
*
|
|
* Ordering guarantee: `value` is written before `status` transitions to `'done'`;
|
|
* `error` is written before `status` transitions to `'error'`. Any reader
|
|
* observing `status === 'done'` is guaranteed `value` is already present.
|
|
*/
|
|
declare class Task<TValue = void, TError = unknown> implements TaskLike<TValue, TError> {
|
|
#private;
|
|
readonly id: string;
|
|
constructor(runFn: (signal: AbortSignal) => Promise<TValue>, config?: TaskConfig);
|
|
get status(): TaskStatus;
|
|
get value(): DeepReadonly<TValue> | undefined;
|
|
get error(): DeepReadonly<TError> | undefined;
|
|
run(): Promise<TValue>;
|
|
abort(): void;
|
|
}
|
|
/**
|
|
* Runs tasks concurrently, deduplicated by task id.
|
|
*
|
|
* If a task with a given id is already in flight, subsequent schedule() calls
|
|
* for that id are silently ignored until the first completes. Tasks are stored
|
|
* so abortAll() can cancel any in-flight work (e.g. on engine cleanup).
|
|
*/
|
|
declare class ConcurrentRunner {
|
|
#private;
|
|
schedule<TValue = void, TError = unknown>(task: TaskLike<TValue, TError>): Promise<TValue>;
|
|
/**
|
|
* Registers a callback to fire when all currently in-flight tasks settle.
|
|
* If the runner is already idle, the callback is never called. If abortAll()
|
|
* is called before the batch settles, the callback is superseded and silently
|
|
* dropped — no stale callbacks, no generation token required by the caller.
|
|
*/
|
|
whenSettled(callback: () => void): void;
|
|
abortAll(): void;
|
|
destroy(): void;
|
|
}
|
|
/**
|
|
* Runs tasks one at a time in submission order.
|
|
*
|
|
* Each schedule() call returns a Promise that resolves or rejects with the
|
|
* task's result when it is eventually executed. Tasks wait in queue until the
|
|
* prior task completes.
|
|
*
|
|
* Serialization is achieved by chaining each task's run() onto the tail of a
|
|
* shared promise chain — no explicit queue or drain loop needed.
|
|
*
|
|
* abortAll() aborts all pending (not yet started) tasks and the currently
|
|
* in-flight task. Pending tasks still run briefly but receive an aborted
|
|
* signal and are expected to exit early.
|
|
*/
|
|
declare class SerialRunner {
|
|
#private;
|
|
schedule<TValue = void, TError = unknown>(task: TaskLike<TValue, TError>): Promise<TValue>;
|
|
/**
|
|
* A promise that resolves when all currently-scheduled tasks have settled.
|
|
* Use the reference as a generation token: capture it after scheduling a
|
|
* batch, then check identity in the resolution callback to detect whether
|
|
* a subsequent abortAll() + new batch has superseded this one.
|
|
*/
|
|
get settled(): Promise<void>;
|
|
/**
|
|
* Registers a callback to fire when all currently-pending tasks settle.
|
|
* If the runner is already idle (no pending or running tasks), the callback
|
|
* is never called. If new tasks are scheduled before the current batch
|
|
* settles, the callback is superseded and silently dropped — no stale
|
|
* callbacks, no generation token required by the caller.
|
|
*/
|
|
whenSettled(callback: () => void): void;
|
|
/** Aborts and clears queued tasks without touching the in-flight task. */
|
|
abortPending(): void;
|
|
abortAll(): void;
|
|
destroy(): void;
|
|
}
|
|
//#endregion
|
|
export { ConcurrentRunner, DeepReadonly, SerialRunner, Task, TaskConfig, TaskLike, TaskStatus };
|
|
//# sourceMappingURL=task.d.ts.map
|