Files
orca/src/main/plugins/plugin-worker-slot-pool.ts
T
mirror 34fa2cd5ca
Skill update round trip / roundtrip (false, macos-latest, copy, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (false, macos-latest, symlink, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (false, ubuntu-latest, copy, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (false, ubuntu-latest, symlink, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (false, ubuntu-latest, symlink, latest) (push) Canceled after 0s
Skill update round trip / roundtrip (false, windows-latest, copy, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (false, windows-latest, symlink, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (true, macos-latest, copy, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (true, macos-latest, symlink, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (true, ubuntu-latest, copy, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (true, ubuntu-latest, symlink, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (true, windows-latest, copy, 1.5.17) (push) Canceled after 0s
Skill update round trip / roundtrip (true, windows-latest, symlink, 1.5.17) (push) Canceled after 0s
source snapshot 2026-09-02
2026-09-02 02:03:16 +08:00

103 lines
2.7 KiB
TypeScript

export type PluginWorkerSlotLease = {
release(): void
}
type SlotWaiter = {
signal: AbortSignal
resolve: (lease: PluginWorkerSlotLease) => void
reject: (error: Error) => void
onAbort: () => void
}
function cancellationError(): Error {
return new Error('plugin worker activation was cancelled')
}
/** Atomically leases the bounded worker slots and hands releases to queued
* activations in FIFO order. */
export class PluginWorkerSlotPool {
private readonly waiters: SlotWaiter[] = []
private leased = 0
private disposed = false
constructor(private readonly capacity: number) {
if (!Number.isInteger(capacity) || capacity <= 0) {
throw new Error('plugin worker capacity must be a positive integer')
}
}
acquire(signal: AbortSignal): Promise<PluginWorkerSlotLease> {
if (this.disposed) {
return Promise.reject(new Error('plugin worker slots are shut down'))
}
if (signal.aborted) {
return Promise.reject(cancellationError())
}
if (this.leased < this.capacity && this.waiters.length === 0) {
this.leased += 1
return Promise.resolve(this.createLease())
}
return new Promise<PluginWorkerSlotLease>((resolve, reject) => {
let cancelled = false
const waiter: SlotWaiter = {
signal,
resolve,
reject,
onAbort: () => {
if (cancelled) {
return
}
cancelled = true
const index = this.waiters.indexOf(waiter)
if (index !== -1) {
this.waiters.splice(index, 1)
}
signal.removeEventListener('abort', waiter.onAbort)
reject(cancellationError())
this.drain()
}
}
this.waiters.push(waiter)
signal.addEventListener('abort', waiter.onAbort, { once: true })
})
}
dispose(): void {
if (this.disposed) {
return
}
this.disposed = true
for (const waiter of this.waiters.splice(0)) {
waiter.signal.removeEventListener('abort', waiter.onAbort)
waiter.reject(new Error('plugin worker slots are shut down'))
}
}
private createLease(): PluginWorkerSlotLease {
let released = false
return {
release: () => {
if (released) {
return
}
released = true
this.leased -= 1
this.drain()
}
}
}
private drain(): void {
while (!this.disposed && this.leased < this.capacity && this.waiters.length > 0) {
const waiter = this.waiters.shift()!
waiter.signal.removeEventListener('abort', waiter.onAbort)
if (waiter.signal.aborted) {
waiter.reject(cancellationError())
continue
}
this.leased += 1
waiter.resolve(this.createLease())
}
}
}