cleanup compute core/server dead paths
This commit is contained in:
parent
6f68c169b6
commit
e6e029cf8a
6 changed files with 1 additions and 121 deletions
|
|
@ -1,11 +1,9 @@
|
|||
import type {
|
||||
WorkerOperationEvent,
|
||||
WorkerOperationKind,
|
||||
WorkerOperationRequest,
|
||||
WorkerOperationState,
|
||||
} from '../api-contracts';
|
||||
|
||||
export type OperationRequest = WorkerOperationRequest;
|
||||
export type OperationState<Result = unknown> = WorkerOperationState<Result>;
|
||||
export type OperationEvent<Result = unknown> = WorkerOperationEvent<Result>;
|
||||
|
||||
|
|
@ -63,5 +61,3 @@ export interface OperationLifecycleConfig {
|
|||
opStaleMs: number;
|
||||
maxCasRetries?: number;
|
||||
}
|
||||
|
||||
export type OperationTransitionStatus = 'queued' | 'running' | 'succeeded' | 'failed';
|
||||
|
|
|
|||
|
|
@ -19,7 +19,3 @@ function resolveDocstoreDir(): string {
|
|||
}
|
||||
|
||||
export const DOCSTORE_DIR = resolveDocstoreDir();
|
||||
|
||||
export function getDocstoreDir(): string {
|
||||
return DOCSTORE_DIR;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
import { getComputeJobConcurrency } from '@openreader/compute-core';
|
||||
|
||||
export class ConcurrencyLimiter {
|
||||
private readonly maxInFlight: number;
|
||||
private inFlight = 0;
|
||||
private readonly queue: Array<() => void> = [];
|
||||
|
||||
constructor(limit: number) {
|
||||
this.maxInFlight = Number.isFinite(limit) && limit >= 1 ? Math.floor(limit) : 1;
|
||||
}
|
||||
|
||||
async run<T>(fn: () => Promise<T>): Promise<T> {
|
||||
await this.acquire();
|
||||
try {
|
||||
return await fn();
|
||||
} finally {
|
||||
this.release();
|
||||
}
|
||||
}
|
||||
|
||||
private acquire(): Promise<void> {
|
||||
if (this.inFlight < this.maxInFlight) {
|
||||
this.inFlight += 1;
|
||||
return Promise.resolve();
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
this.queue.push(() => {
|
||||
this.inFlight += 1;
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private release(): void {
|
||||
this.inFlight = Math.max(0, this.inFlight - 1);
|
||||
const next = this.queue.shift();
|
||||
if (next) next();
|
||||
}
|
||||
}
|
||||
|
||||
export const LOCAL_COMPUTE_LIMITER = new ConcurrencyLimiter(getComputeJobConcurrency());
|
||||
|
|
@ -3,13 +3,9 @@ import { isWorkerClientConfigAvailable, WorkerComputeBackend } from '@/lib/serve
|
|||
|
||||
let backendPromise: Promise<ComputeBackend> | null = null;
|
||||
|
||||
async function createBackend(): Promise<ComputeBackend> {
|
||||
return new WorkerComputeBackend();
|
||||
}
|
||||
|
||||
export async function getCompute(): Promise<ComputeBackend> {
|
||||
if (!backendPromise) {
|
||||
backendPromise = createBackend().catch((error) => {
|
||||
backendPromise = Promise.resolve(new WorkerComputeBackend()).catch((error) => {
|
||||
backendPromise = null;
|
||||
throw error;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ import type {
|
|||
import type { PdfLayoutProgress, WhisperAlignJobBase } from '@openreader/compute-core/api-contracts';
|
||||
import type { PdfLayoutJobResult, WorkerOperationState } from '@openreader/compute-core/api-contracts';
|
||||
|
||||
export type ComputeMode = 'worker';
|
||||
|
||||
export interface WhisperAlignInput extends WhisperAlignJobBase {
|
||||
audioBuffer?: TTSAudioBuffer;
|
||||
audioObjectKey?: string;
|
||||
|
|
|
|||
|
|
@ -1,65 +0,0 @@
|
|||
import { expect, test } from '@playwright/test';
|
||||
import { ConcurrencyLimiter } from '../../src/lib/server/compute/concurrency-limiter';
|
||||
|
||||
function sleep(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
test.describe('compute-concurrency-limiter', () => {
|
||||
test('caps active jobs at configured limit', async () => {
|
||||
const limiter = new ConcurrencyLimiter(2);
|
||||
let inFlight = 0;
|
||||
let maxInFlightSeen = 0;
|
||||
|
||||
const jobs = Array.from({ length: 6 }, (_, i) => limiter.run(async () => {
|
||||
inFlight += 1;
|
||||
maxInFlightSeen = Math.max(maxInFlightSeen, inFlight);
|
||||
await sleep(20 + (i % 2) * 5);
|
||||
inFlight -= 1;
|
||||
return i;
|
||||
}));
|
||||
|
||||
const result = await Promise.all(jobs);
|
||||
expect(result).toEqual([0, 1, 2, 3, 4, 5]);
|
||||
expect(maxInFlightSeen).toBe(2);
|
||||
});
|
||||
|
||||
test('queues in FIFO order when saturated', async () => {
|
||||
const limiter = new ConcurrencyLimiter(1);
|
||||
const starts: number[] = [];
|
||||
|
||||
const one = limiter.run(async () => {
|
||||
starts.push(1);
|
||||
await sleep(25);
|
||||
});
|
||||
const two = limiter.run(async () => {
|
||||
starts.push(2);
|
||||
await sleep(5);
|
||||
});
|
||||
const three = limiter.run(async () => {
|
||||
starts.push(3);
|
||||
await sleep(1);
|
||||
});
|
||||
|
||||
await Promise.all([one, two, three]);
|
||||
expect(starts).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
test('releases slot after failure', async () => {
|
||||
const limiter = new ConcurrencyLimiter(1);
|
||||
let startedSecond = false;
|
||||
|
||||
const first = limiter.run(async () => {
|
||||
await sleep(10);
|
||||
throw new Error('boom');
|
||||
});
|
||||
const second = limiter.run(async () => {
|
||||
startedSecond = true;
|
||||
return 'ok';
|
||||
});
|
||||
|
||||
await expect(first).rejects.toThrow('boom');
|
||||
await expect(second).resolves.toBe('ok');
|
||||
expect(startedSecond).toBeTruthy();
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue