Files
dj/integration-work/test_polling_policy.cjs

44 lines
4.6 KiB
JavaScript

const fs=require('node:fs'),vm=require('node:vm'),assert=require('node:assert/strict');
const ts=require('D:/web/dj/huobao-source/backend/node_modules/typescript');
const root='D:/web/dj/huobao-source/backend/src/services/';
function moduleOf(file,requires={}){
const m={exports:{}};vm.runInNewContext(ts.transpileModule(fs.readFileSync(root+file,'utf8'),{compilerOptions:{module:ts.ModuleKind.CommonJS,target:ts.ScriptTarget.ES2022}}).outputText,{module:m,exports:m.exports,require:n=>requires[n],URL,Buffer});return m.exports;
}
const routing=moduleOf('worker-routing.ts'),policy=moduleOf('local-task-tracking.ts',{'./worker-routing.js':routing});
const text=fs.readFileSync(root+'generation.ts','utf8'),tree=ts.createSourceFile('generation.ts',text,ts.ScriptTarget.Latest,true);
const fn=tree.statements.find(n=>ts.isFunctionDeclaration(n)&&n.name.text==='pollTask');
const compiled=ts.transpileModule(fn.getText(tree),{compilerOptions:{target:ts.ScriptTarget.ES2022}}).outputText;
const taskId=Buffer.from('gpu3:11111111-1111-4111-8111-111111111111').toString('base64url');
assert.equal(policy.isLocalQueuedTask({baseUrl:'http://192.168.110.111:18792',provider:'minimax'},taskId),true);
assert.equal(policy.isLocalQueuedTask({baseUrl:'https://example.com',provider:'minimax'},taskId),false);
assert.equal(policy.isLocalQueuedTask({baseUrl:'http://192.168.110.111:18792',provider:'minimax'},'unknown'),false);
async function run(type,sequence,{external=false,cancelAt=0}={}){
let row={id:1,type,status:'processing',params:'{}'},calls=0,failed=null,completed=false,stages=[];
const chain={from(){return this},where(){return Promise.resolve(row?[{...row}]:[])}};
const adapter={buildPollRequest:()=>({url:'http://poll',method:'GET',headers:{}}),parsePollResponse:r=>r};
const ctx={db:{select:()=>chain,update:()=>({set:patch=>({where:()=>{if(row.status==='processing'){Object.assign(row,patch);if(patch.stage)stages.push(patch.stage)}return Promise.resolve()}})})},
schema:{sysTask:{id:'id',status:'status'}},eq:()=>{},and:()=>{},taskLabel:x=>x,parseTaskParams:JSON.parse,
isLocalQueuedTask:policy.isLocalQueuedTask,taskPollingProfile:policy.taskPollingProfile,
getImageAdapter:()=>adapter,getVideoAdapter:()=>adapter,saveRouting:async()=>{},
failTask:async(id,message,code)=>{failed={message,code};row.status='failed'},
handleImageComplete:async()=>{completed=true;row.status='completed'},handleVideoComplete:async()=>{completed=true;row.status='completed'},
logTaskProgress:()=>{},logTaskSuccess:()=>{},logTaskWarn:()=>{},redactUrl:x=>x,now:()=>new Date().toISOString(),
setTimeout:cb=>setImmediate(cb),Date,Math,Promise,AbortSignal,cancellingTasks:new Set(),
fetch:async(url,options)=>{assert.equal(options.method,'GET');calls++;assert.ok(calls<1200);if(cancelAt&&calls===cancelAt)row.status='failed';const result=sequence(calls);if(result instanceof Error)throw result;return{ok:true,json:async()=>result}}};
vm.createContext(ctx);vm.runInContext(compiled,ctx);
const config={provider:type==='video'?'minimax':'openai',baseUrl:external?'https://example.com':'http://192.168.110.111:18792'};
await ctx.pollTask({...row},config,taskId);return{calls,failed,completed,stages};
}
(async()=>{
const done={status:'completed',videoUrl:'video',imageUrl:'image'};
let r=await run('video',n=>n<=360?{status:'processing',stage:'queued'}:done);assert.equal(r.calls,361);assert.equal(r.completed,true);assert.equal(r.failed,null);
r=await run('image',n=>n<=150?{status:'processing',stage:'queued'}:done);assert.equal(r.calls,151);assert.equal(r.completed,true);
r=await run('video',n=>n<3?new Error('timeout'):n<6?{status:'processing',stage:'running'}:done);assert.ok(r.stages.includes('reconnecting'));assert.equal(r.completed,true);
r=await run('video',()=>({status:'processing',stage:'missing'}));assert.equal(r.calls,3);assert.equal(r.failed.code,'upstream_missing');
r=await run('video',n=>n<3?{status:'processing',stage:'missing'}:done);assert.equal(r.failed,null);assert.equal(r.completed,true);
r=await run('video',()=>({status:'failed',error:'actual worker failure'}));assert.equal(r.calls,1);assert.equal(r.failed.code,'generation_failed');
r=await run('video',()=>({status:'processing'}),{external:true});assert.equal(r.calls,300);assert.ok(r.failed.message.includes('attempts exhausted'));
r=await run('video',()=>({status:'processing'}),{cancelAt:5});assert.equal(r.calls,5);assert.equal(r.completed,false);
console.log('PASS: local video >300/image >120 polls, network recovery, missing confirmation, real failure, external limits unchanged, cancellation stops tracking');
})().catch(e=>{console.error(e);process.exit(1)});