fix(pi): single-flight managed extension materialization
This commit is contained in:
@@ -139,6 +139,7 @@ export class PiManagedExtensionHost {
|
|||||||
private readonly registrations = new Map<string, WorkerRegistrationRecord>();
|
private readonly registrations = new Map<string, WorkerRegistrationRecord>();
|
||||||
private readonly runBindings = new Map<string, string>();
|
private readonly runBindings = new Map<string, string>();
|
||||||
private readonly requestFlights = new Set<Promise<void>>();
|
private readonly requestFlights = new Set<Promise<void>>();
|
||||||
|
private readonly extensionMaterializations = new Map<string, Promise<string>>();
|
||||||
private subagentBridge: PiExtensionSubagentBridge | undefined;
|
private subagentBridge: PiExtensionSubagentBridge | undefined;
|
||||||
private productTools: PiProductTools | undefined;
|
private productTools: PiProductTools | undefined;
|
||||||
private server: Server | null = null;
|
private server: Server | null = null;
|
||||||
@@ -183,7 +184,15 @@ export class PiManagedExtensionHost {
|
|||||||
}
|
}
|
||||||
const bridgeUrl = await this.start();
|
const bridgeUrl = await this.start();
|
||||||
await mkdir(input.extensionsDir, { recursive: true });
|
await mkdir(input.extensionsDir, { recursive: true });
|
||||||
const extensionPath = await materializeMakelorePiExtension(input.extensionsDir);
|
let materialization = this.extensionMaterializations.get(input.extensionsDir);
|
||||||
|
if (!materialization) {
|
||||||
|
materialization = materializeMakelorePiExtension(input.extensionsDir).catch((error) => {
|
||||||
|
this.extensionMaterializations.delete(input.extensionsDir);
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
this.extensionMaterializations.set(input.extensionsDir, materialization);
|
||||||
|
}
|
||||||
|
const extensionPath = await materialization;
|
||||||
const role = input.role ?? 'parent';
|
const role = input.role ?? 'parent';
|
||||||
if (role === 'child' && !input.runId?.trim()) {
|
if (role === 'child' && !input.runId?.trim()) {
|
||||||
throw new Error('Child extension registration requires a parent run id');
|
throw new Error('Child extension registration requires a parent run id');
|
||||||
|
|||||||
@@ -35,6 +35,26 @@ async function post(
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('managed Pi extension bridge', () => {
|
describe('managed Pi extension bridge', () => {
|
||||||
|
it('single-flights the shared managed extension for concurrent worker registration', async () => {
|
||||||
|
const root = await mkdtemp(path.join(tmpdir(), 'makelore-pi-extension-concurrent-'));
|
||||||
|
roots.push(root);
|
||||||
|
const host = new PiManagedExtensionHost();
|
||||||
|
hosts.push(host);
|
||||||
|
|
||||||
|
const registrations = await Promise.all(Array.from({ length: 8 }, async (_, index) => (
|
||||||
|
await host.registerWorker({
|
||||||
|
conversationId: `conversation-${index + 1}`,
|
||||||
|
generation: 1,
|
||||||
|
projectId: `project-${index + 1}`,
|
||||||
|
extensionsDir: root,
|
||||||
|
})
|
||||||
|
)));
|
||||||
|
|
||||||
|
expect(new Set(registrations.map(({ extensionPath }) => extensionPath)).size).toBe(1);
|
||||||
|
expect(host.getDiagnostics().registrations).toEqual({ parent: 8, child: 0 });
|
||||||
|
await Promise.all(registrations.map(({ dispose }) => dispose()));
|
||||||
|
});
|
||||||
|
|
||||||
it('finishes a queued HTTP request while closing a holder and waiter', async () => {
|
it('finishes a queued HTTP request while closing a holder and waiter', async () => {
|
||||||
const root = await mkdtemp(path.join(tmpdir(), 'makelore-pi-extension-close-'));
|
const root = await mkdtemp(path.join(tmpdir(), 'makelore-pi-extension-close-'));
|
||||||
roots.push(root);
|
roots.push(root);
|
||||||
|
|||||||
Reference in New Issue
Block a user