/** * 复用导入的合作调度机制,同时维持copy专用取消/配置错误码。 * 它不分配ID或落盘,单个原生encode/解码步骤的大小仍必须由调用者另外限制。 */ import {fault} from '../canvas-core/values.ts'; import {createImportBudget,type ImportScheduling} from './import-budget.ts'; /** Share import scheduling while retaining the copy cancellation/error contract. */ /** 复制任务的 ImportBudget 包装:构造与每次 step 都先检查取消,错误码使用 copy_aborted。 * 只预校验 frameBudgetMs;units/时钟/调度器沿用底层合同,单位可以是记录数或由调用方折算的字节工作量。 * 与同一个包装交互应顺序 await;没有独立计数器、持久进度或强制抢占能力。 */ export function createCopyBudget(signal:AbortSignal,options:ImportScheduling={}){ if(signal.aborted)throw fault('copy_aborted'); if(options.frameBudgetMs!==undefined&&(!Number.isFinite(options.frameBudgetMs)||options.frameBudgetMs<=0))throw fault('invalid_copy_budget'); const budget=createImportBudget(signal,options); /** 只在处理错误时 signal 已取消才改成 copy_aborted;其它错误保留原对象。 * 因此取消和宿主调度失败并发出现时,取消优先,不一定暴露原始调度错误。 */ const fail=(error:unknown):never=>{if(signal.aborted)throw fault('copy_aborted');throw error;}; /** 每次step先查copy取消,保持底层同步返回undefined或异步让出的原调度语义。 */ return Object.freeze({step(units=1):Promise|undefined{ if(signal.aborted)throw fault('copy_aborted'); try{return budget.step(units)?.catch(fail);}catch(error){return fail(error);} }}); }