legacy-sync-worker.test.mjs 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. import assert from 'node:assert/strict';
  2. import { spawn } from 'node:child_process';
  3. import { createServer } from 'node:http';
  4. import test from 'node:test';
  5. test('one worker tick requests every configured data set exactly once', async () => {
  6. const requests = [];
  7. const server = createServer((request, response) => {
  8. let body = '';
  9. request.setEncoding('utf8');
  10. request.on('data', (chunk) => { body += chunk; });
  11. request.on('end', () => {
  12. requests.push({ url: request.url, body: JSON.parse(body) });
  13. response.writeHead(200, { 'Content-Type': 'application/json' });
  14. response.end(JSON.stringify({ success: true, data: { processed: 0, failures: 0, hasMore: false } }));
  15. });
  16. });
  17. await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
  18. const address = server.address();
  19. assert(address && typeof address === 'object');
  20. const datasets = ['learning-records', 'appointments', 'lessons'];
  21. const child = spawn(process.execPath, ['scripts/run-legacy-sync-worker.mjs', '--once'], {
  22. cwd: process.cwd(),
  23. env: {
  24. ...process.env,
  25. XIAOSHU_FUNCTION_URL: `http://127.0.0.1:${address.port}`,
  26. XIAOSHU_SYNC_OPERATOR_TOKEN: 'test-session',
  27. XIAOSHU_SYNC_DATASETS: datasets.join(','),
  28. XIAOSHU_SYNC_HEALTH_PORT: '0',
  29. },
  30. stdio: ['ignore', 'pipe', 'pipe'],
  31. });
  32. let stderr = '';
  33. child.stderr.on('data', (chunk) => { stderr += chunk; });
  34. const exitCode = await new Promise((resolve) => child.on('close', resolve));
  35. await new Promise((resolve) => server.close(resolve));
  36. assert.equal(exitCode, 0, stderr);
  37. assert.deepEqual(requests.map((entry) => entry.url), datasets.map(() => '/xiaoshu/ops/gateway-v3'));
  38. assert.deepEqual(requests.map((entry) => entry.body.params.dataset).sort(), datasets.slice().sort());
  39. assert(requests.every((entry) => entry.body.params.operation === 'ops/sync/run'));
  40. assert(requests.every((entry) => entry.body.token === 'test-session'));
  41. });
  42. test('dependent review records wait until learning history is fully caught up', async () => {
  43. const requested=[];
  44. const server=createServer((request,response)=>{
  45. let body='';request.setEncoding('utf8');request.on('data',(chunk)=>{body+=chunk;});request.on('end',()=>{
  46. const dataset=JSON.parse(body).params.dataset;requested.push(dataset);
  47. response.writeHead(200,{'Content-Type':'application/json'});
  48. response.end(JSON.stringify({success:true,data:{processed:1,failures:0,hasMore:dataset==='learning-records'}}));
  49. });
  50. });
  51. await new Promise((resolve)=>server.listen(0,'127.0.0.1',resolve));
  52. const address=server.address();assert(address&&typeof address==='object');
  53. const child=spawn(process.execPath,['scripts/run-legacy-sync-worker.mjs','--once'],{cwd:process.cwd(),env:{...process.env,XIAOSHU_FUNCTION_URL:`http://127.0.0.1:${address.port}`,XIAOSHU_SYNC_OPERATOR_TOKEN:'test-session',XIAOSHU_SYNC_DATASETS:'memory-records,learning-records,lessons,appointments',XIAOSHU_SYNC_HEALTH_PORT:'0'},stdio:['ignore','pipe','pipe']});
  54. let stderr='';child.stderr.on('data',(chunk)=>{stderr+=chunk;});
  55. const exitCode=await new Promise((resolve)=>child.on('close',resolve));await new Promise((resolve)=>server.close(resolve));
  56. assert.equal(exitCode,0,stderr);assert(requested.includes('learning-records'));assert(requested.includes('appointments'));assert(requested.includes('lessons'));assert(!requested.includes('memory-records'));assert(requested.indexOf('appointments')<requested.indexOf('lessons'));
  57. });