| 1234567891011121314151617 |
- import {candidateCode} from './candidate-code.mjs';
- import {readFileSync,writeFileSync,mkdirSync} from 'node:fs';
- import {randomBytes} from 'node:crypto';
- const base='https://server.xiaoshu.pro/parse',app=process.env.XIAOSHU_PARSE_APP_ID||'7pIbDBJmKx_main',master=process.env.XIAOSHU_MASTER_KEY,token=process.env.XIAOSHU_SYNC_OPERATOR_TOKEN;if(!master||!token)throw Error('Missing authorized config');
- const headers={'Content-Type':'application/json','X-Parse-Application-Id':app,'X-Parse-Master-Key':master};
- async function parse(path,method='GET',body){const r=await fetch(base+path,{method,headers,body:body?JSON.stringify(body):undefined,signal:AbortSignal.timeout(20000)});const d=await r.json();if(!r.ok||d.error)throw Error('Diagnostic setup failed HTTP '+r.status);return d;}
- const meR=await fetch(base+'/users/me',{headers:{'X-Parse-Application-Id':app,'X-Parse-Session-Token':token}}),me=await meR.json();if(!me.objectId)throw Error('Unknown operator');
- const row=(await parse('/classes/Function?'+new URLSearchParams({where:JSON.stringify({path:'xiaoshu/ops/gateway-v3'}),limit:'2'}))).results;if(row.length!==1)throw Error('Ambiguous gateway');
- const out='tmp/admin-data-2026-10-15';mkdirSync(out,{recursive:true,mode:0o700});writeFileSync(out+'/online-before.json',JSON.stringify(row[0]),{mode:0o600});
- const operations=process.argv.slice(2).length?process.argv.slice(2):['ops/dashboard/summary','ops/stores/list','ops/users/list','ops/coaches/list','ops/schedule/calendar','ops/payroll/overview'];
- const prelude=`const __perf=[];const __perfSql=new Proxy({},{get(target,key){const f=Psql[key];if(typeof f!=='function')return f;return async function(...args){const at=Date.now();try{return await f.apply(Psql,args);}finally{__perf.push({kind:'sql',method:key,ms:Date.now()-at,query:typeof args[0]==='string'?args[0]:String(key),args:typeof args[0]==='string'?args[1]:undefined});}};}});class __PerfQuery extends Parse.Query {async find(...args){const at=Date.now();try{return await super.find(...args);}finally{__perf.push({kind:'parse',method:'find',className:this.className,ms:Date.now()-at});}}async count(...args){const at=Date.now();try{return await super.count(...args);}finally{__perf.push({kind:'parse',method:'count',className:this.className,ms:Date.now()-at});}}}`;
- const baseCode=process.env.PERF_CANDIDATE?candidateCode(row[0].code,{temporaryView:true}):row[0].code;
- const code=prelude+'\n'+baseCode.replaceAll('Psql.','__perfSql.').replaceAll('new Parse.Query(','new __PerfQuery(')+`\nconst __original=handler;handler=async function(request,response){if(request.user?.id!==${JSON.stringify(me.objectId)}||Date.now()>${Date.now()+900000}||!${JSON.stringify(operations)}.includes(request.body?.params?.operation))return response.status(403).json({success:false});const start=Date.now();let status=200;const wrapped={status(s){status=s;return this;},json(body){return response.status(status).json({...body,__profile:{elapsedMs:Date.now()-start,entries:__perf}});}};return __original(request,wrapped);};`;
- new Function(code);const path='xiaoshu/system/perf-read-'+randomBytes(10).toString('hex');let fn;
- try{fn=await parse('/classes/Function','POST',{name:path,path,code,type:'standalone',enabled:true,params:[],paramList:[],respType:'json'});
- for(const operation of operations){const at=Date.now(),params={operation,page:1,pageSize:20,month:'2026-10',dateFrom:'2026-10-15',dateTo:'2026-10-21',source:'database',filters:{status:'all'}};const r=await fetch(base.replace('/parse','/api/functions/')+path,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({token,params}),signal:AbortSignal.timeout(90000)});const d=await r.json();writeFileSync(out+'/'+operation.replaceAll('/','-')+(process.env.PERF_CANDIDATE?'-candidate':'')+'-profile.json',JSON.stringify(d),{mode:0o600});console.log(JSON.stringify({operation,http:r.status,elapsedMs:Date.now()-at,serverMs:d.__profile?.elapsedMs,queries:d.__profile?.entries?.length,top:d.__profile?.entries?.toSorted((a,b)=>b.ms-a.ms).slice(0,6).map(({args,...e})=>({...e,query:e.query?.slice(0,200)})),error:d.message}));}
- }finally{if(fn)await parse('/classes/Function/'+fn.objectId,'DELETE');}
|