mirror of
https://github.com/stablyai/orca.git
synced 2026-11-15 10:27:33 +00:00
refactor(github): organize concrete feature owners (#41601)
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
import { execFile } from 'node:child_process'
|
||||
import { promisify } from 'node:util'
|
||||
|
||||
// Repo-scoped operations need the WSL-aware runner; this legacy wrapper serves generic commands.
|
||||
export const execFileAsync = promisify(execFile)
|
||||
@@ -0,0 +1,21 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { acquire, release } from './github-operation-slots'
|
||||
|
||||
describe('GitHub concurrency', () => {
|
||||
it('removes aborted waiters without consuming a permit', async () => {
|
||||
await Promise.all([acquire(), acquire(), acquire(), acquire()])
|
||||
const controller = new AbortController()
|
||||
const queued = acquire(controller.signal)
|
||||
|
||||
controller.abort()
|
||||
|
||||
await expect(queued).rejects.toMatchObject({ name: 'AbortError' })
|
||||
release()
|
||||
await expect(acquire()).resolves.toBeUndefined()
|
||||
|
||||
release()
|
||||
release()
|
||||
release()
|
||||
release()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,54 @@
|
||||
const MAX_CONCURRENT = 4
|
||||
|
||||
let running = 0
|
||||
|
||||
type QueueEntry = {
|
||||
signal?: AbortSignal
|
||||
start: () => void
|
||||
reject: (error: Error) => void
|
||||
}
|
||||
|
||||
const queue: QueueEntry[] = []
|
||||
|
||||
function githubOperationAbortError(): Error {
|
||||
const error = new Error('GitHub operation aborted')
|
||||
error.name = 'AbortError'
|
||||
return error
|
||||
}
|
||||
|
||||
export function acquire(signal?: AbortSignal): Promise<void> {
|
||||
if (signal?.aborted) {
|
||||
return Promise.reject(githubOperationAbortError())
|
||||
}
|
||||
if (running < MAX_CONCURRENT) {
|
||||
running += 1
|
||||
return Promise.resolve()
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const entry: QueueEntry = {
|
||||
signal,
|
||||
reject,
|
||||
start: () => {
|
||||
signal?.removeEventListener('abort', onAbort)
|
||||
running += 1
|
||||
resolve()
|
||||
}
|
||||
}
|
||||
const onAbort = (): void => {
|
||||
const index = queue.indexOf(entry)
|
||||
if (index === -1) {
|
||||
return
|
||||
}
|
||||
queue.splice(index, 1)
|
||||
reject(githubOperationAbortError())
|
||||
}
|
||||
signal?.addEventListener('abort', onAbort, { once: true })
|
||||
queue.push(entry)
|
||||
})
|
||||
}
|
||||
|
||||
export function release(): void {
|
||||
running -= 1
|
||||
const next = queue.shift()
|
||||
next?.start()
|
||||
}
|
||||
Reference in New Issue
Block a user