Negotiate and decode snapshot-bound canonical model streams
This commit is contained in:
@@ -10,9 +10,12 @@ import { setTimeout as pause } from 'node:timers/promises';
|
||||
const source=resolve(import.meta.dirname,'../..'),directory=await mkdtemp(join(tmpdir(),'endoleap-proxy-check-')),received=[];
|
||||
const account='10000000-0000-4000-8000-000000000004',key='90000000-0000-4000-8000-000000000002';
|
||||
const responseBytes=' { "protocol_version":2, "request_id":"'+key+'", "status":"not-applied", "terminal":true, "error":"fixture_rejection", "extension":{"retained":true} }\n';
|
||||
let streamRelease;const streamGate=new Promise(resolve=>streamRelease=resolve);
|
||||
const streamPrefix='{"streamVersion":1,"kind":"header"}\n',streamTail='{"streamVersion":1,"kind":"complete"}\n';
|
||||
const upstream=createServer(async(request,response)=>{
|
||||
const chunks=[];for await(const chunk of request)chunks.push(chunk);
|
||||
received.push({path:request.url,body:Buffer.concat(chunks),headers:request.headers});
|
||||
if(request.url.endsWith('/model')&&request.headers.accept==='application/vnd.foundry.canvas-model+ndjson;version=1'){response.writeHead(200,{'Content-Type':'application/vnd.foundry.canvas-model+ndjson;version=1'});response.write(streamPrefix);await streamGate;response.end(streamTail);return;}
|
||||
response.writeHead(request.url.endsWith('/model/operations')?409:200,{'Content-Type':'application/json'});
|
||||
response.end(request.url.endsWith('/model/operations')?responseBytes:'{"id":"fixture"}');
|
||||
});
|
||||
@@ -60,10 +63,15 @@ try{
|
||||
const aiEvents=await fetch(`http://127.0.0.1:${port}/api/foundry/${aiPath}/${key}?after_seq=41&limit=100`);await aiEvents.text();assert.equal(aiEvents.status,200);
|
||||
assert.ok(received.some(item=>item.path.endsWith('/ai/runs/'+key+'?limit=100&after_seq=41')));
|
||||
console.log('PASS frozen AI bytes, identity, version header, admission receipt and event cursor cross the actual Next proxy');
|
||||
const streamed=await fetch(`http://127.0.0.1:${port}/api/foundry/${path.replace('/operations','')}`,{headers:{Accept:'application/vnd.foundry.canvas-model+ndjson;version=1'}});
|
||||
assert.equal(streamed.headers.get('content-type'),'application/vnd.foundry.canvas-model+ndjson;version=1');
|
||||
const reader=streamed.body.getReader(),first=await reader.read();assert.equal(new TextDecoder().decode(first.value),streamPrefix);streamRelease();let rest='';while(true){const next=await reader.read();if(next.done)break;rest+=new TextDecoder().decode(next.value);}assert.equal(rest,streamTail);reader.releaseLock();
|
||||
console.log('PASS negotiated canonical NDJSON and first chunk cross the actual Next proxy before the gated tail');
|
||||
const before=received.length,invalid=await fetch(`http://127.0.0.1:${port}/api/foundry/${path}/unexpected/extra`,{signal:AbortSignal.timeout(10000)});await invalid.text();assert.equal(invalid.status,404);assert.equal(received.length,before);
|
||||
console.log('PASS actual Next proxy preserves frozen request bytes/key/account and raw terminal receipt above 1 MiB');
|
||||
console.log('PASS canonical route allowlist rejects unexpected paths without contacting the upstream');
|
||||
}finally{
|
||||
streamRelease();
|
||||
if(next?.pid){const exited=new Promise(resolve=>{if(next.exitCode!==null)resolve();else next.once('exit',resolve)});try{process.kill(-next.pid,'SIGTERM')}catch{}await Promise.race([exited,pause(3000)]);if(next.exitCode===null){try{process.kill(-next.pid,'SIGKILL')}catch{}}}
|
||||
upstream.closeAllConnections();await new Promise(resolve=>upstream.close(resolve));await rm(directory,{recursive:true,force:true,maxRetries:5});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user