| 123456789101112131415161718 |
- import {test} from 'node:test';import assert from 'node:assert/strict';import {PGlite} from '@electric-sql/pglite';import {readFileSync,existsSync} from 'node:fs';import vm from 'node:vm';
- const file=new URL('../cloud/lesson-export.js',import.meta.url);
- test('export jobs are idempotent, owner scoped, globally leased and cancellation fences workers',async()=>{
- assert.ok(existsSync(file),'durable export implementation exists');const db=new PGlite();
- try{
- await db.exec(readFileSync(new URL('../sql/lesson-export.sql',import.meta.url),'utf8'));
- const adapter=tx=>({query:async(s,p=[])=>(await tx.query(s,p)).rows,one:async(s,p=[])=>(await tx.query(s,p)).rows[0],none:async(s,p=[])=>{await tx.query(s,p);}});
- const Psql={...adapter(db),tx:work=>db.transaction(tx=>work(adapter(tx)))};
- const context={current:{id:'owner'},company:'co',roles:['ops-manager'],isSuperAdmin:true};
- const ctx=vm.createContext({Psql,text:v=>String(v??''),number:v=>Number(v)||0,companyIdOf:c=>c.company,roleOf:c=>c.roles[0],requireRole:()=>{},requireSuperAdmin:c=>{if(!c.isSuperAdmin)throw Error('forbidden');},fail:(_,m)=>{throw Error(m);},Date,JSON});vm.runInContext(readFileSync(file,'utf8'),ctx);
- const input={idempotencyKey:'export-key-12345678',search:'林'};
- const first=await ctx.lessonExportCreate(context,input),again=await ctx.lessonExportCreate(context,input);assert.equal(first.jobId,again.jobId);
- await assert.rejects(ctx.lessonExportStatus({...context,current:{id:'other'}},{jobId:first.jobId}),/未找到/);
- const claim=await ctx.lessonExportClaim(context);assert.equal(claim.jobId,first.jobId);assert.ok(claim.lease);assert.equal((await ctx.lessonExportClaim(context)).jobId,undefined);
- await ctx.lessonExportCancel(context,{jobId:first.jobId});await assert.rejects(ctx.lessonExportChunk(context,{jobId:first.jobId,lease:claim.lease,offset:0}),/租约/);
- assert.equal((await ctx.lessonExportStatus(context,{jobId:first.jobId})).status,'cancelled');
- }finally{await db.close();}
- });
|