| 123456789101112 |
- // Temporary, operator-bound read-only diagnostics; no persistent application changes.
- import {readFileSync,writeFileSync} from 'node:fs';
- import {randomBytes} from 'node:crypto';
- const app=process.env.XIAOSHU_PARSE_APP_ID,token=process.env.XIAOSHU_SYNC_OPERATOR_TOKEN,master=process.env.XIAOSHU_MASTER_KEY,base='https://server.xiaoshu.pro/parse';
- if(!app||!token||!master)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 me=await(await fetch(base+'/users/me',{headers:{'X-Parse-Application-Id':app,'X-Parse-Session-Token':token}})).json();if(!me.objectId)throw Error('Invalid operator');
- const jobs=JSON.parse(readFileSync(process.argv[2],'utf8'));if(jobs.some(j=>!/^\s*(SELECT|WITH|EXPLAIN)\b/i.test(j.sql)))throw Error('Select jobs required');
- const tempView=readFileSync('scripts/sql/admin-read-performance.sql','utf8').replace('CREATE OR REPLACE VIEW','CREATE TEMP VIEW');
- const path='xiaoshu/system/perf-sql-'+randomBytes(10).toString('hex'),code=`const jobs=${JSON.stringify(jobs)};async function handler(request,response){if(request.user?.id!==${JSON.stringify(me.objectId)}||Date.now()>${Date.now()+1200000})return response.status(403).json({success:false});const job=jobs.find(j=>j.name===request.body?.params?.name);if(!job)return response.status(400).json({success:false});const start=Date.now();try{const rows=await Psql.tx(async tx=>{if(job.tempView){await tx.none('SET LOCAL search_path=pg_temp,public');await tx.none(${JSON.stringify(tempView)});}else await tx.none('SET TRANSACTION READ ONLY');await tx.none(\"SET LOCAL statement_timeout='60s'\");if(job.jitOff)await tx.none('SET LOCAL jit=off');const rows=await tx.query(job.sql,job.args||[]);if(job.tempView)await tx.none('DROP VIEW pg_temp.\"ReviewRewardIncome\"');return rows;});return response.json({success:true,ms:Date.now()-start,rows});}catch(e){return response.status(500).json({success:false,ms:Date.now()-start,error:e.message});}}`;
- let fn;try{fn=await parse('/classes/Function','POST',{name:path,path,code,type:'standalone',enabled:true,params:[],paramList:[],respType:'json'});for(const j of jobs){const r=await fetch(base.replace('/parse','/api/functions/')+path,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({token,params:{name:j.name}}),signal:AbortSignal.timeout(75000)}),data=await r.json();writeFileSync('tmp/admin-data-2026-10-15/'+j.name+'.json',JSON.stringify(data),{mode:0o600});console.log(JSON.stringify({name:j.name,success:data.success,ms:data.ms,error:data.error,rows:data.rows?.length}));}}finally{if(fn)await parse('/classes/Function/'+fn.objectId,'DELETE');}
|