perf(report): load side wrinkle layers after report entry
This commit is contained in:
+51
-5
@@ -31,6 +31,32 @@ const CaptureDiagnostics = require('./lib/capture-diagnostics.js');
|
||||
const WrinkleViews = require('./lib/wrinkle-views.js');
|
||||
const captureFunnel = require('./lib/capture-funnel.js')(path.join(DATA_ROOT, 'capture-funnel.jsonl'));
|
||||
const accounts = require('./lib/accounts.js')(path.join(DATA_ROOT, 'accounts'));
|
||||
const wrinkleJobs = require('./lib/wrinkle-jobs.js')({
|
||||
dir:path.join(DATA_ROOT,'wrinkle-jobs'),
|
||||
collect:async context=>WrinkleViews.forReport(await WrinkleViews.collect(context.primary,context.photos,{
|
||||
key:CRED.key,secret:CRED.secret,url:FACEPP_URL,gapMs:process.env.NODE_ENV==='test'?0:4000,deadline:Date.now()+60000
|
||||
})),
|
||||
load(owner,id) {
|
||||
const snapshot=accounts.reportSnapshot(owner,id);
|
||||
if (!snapshot) return null;
|
||||
return {primary:{left_side_result:snapshot.payload.side?.left,right_side_result:snapshot.payload.side?.right},
|
||||
photos:{left:stripDataPrefix(snapshot.photos[1]||''),right:stripDataPrefix(snapshot.photos[2]||'')}};
|
||||
},
|
||||
complete(owner,id,views,cost) {
|
||||
accounts.updateWrinkleViews(owner,id,views);
|
||||
const rec=findRecord(id);
|
||||
if (!rec || rec.owner_id!==owner) return;
|
||||
rec.wrinkle_view_status=Object.fromEntries(['left','right'].map(v=>[v,{status:views[v]?.status||'unavailable',error_code:views[v]?.error_code||null}]));
|
||||
rec.wrinkle_cost_ms=cost;rec.updated_at=nowIso();updateRecord(rec);
|
||||
if (rec.raw_file) {
|
||||
const file=path.join(DATA_DIR,path.basename(rec.raw_file));
|
||||
try {
|
||||
const raw=JSON.parse(fs.readFileSync(file,'utf8'));raw.wrinkle_views=views;
|
||||
fs.writeFileSync(file+'.wrinkle.tmp',JSON.stringify(raw),{mode:0o600});fs.renameSync(file+'.wrinkle.tmp',file);
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* 服务端评分引擎:与 C 端同一份公式(禁止复制公式,直接复用) */
|
||||
const SkinScore = require('./js/skin-score.js');
|
||||
@@ -326,17 +352,17 @@ function fillFailure(rec, code) {
|
||||
}
|
||||
|
||||
/* 执行一次检测:计时调用 Face++,按结果补全记录(成功/失败都落库)。返回 Face++ 原始返回 */
|
||||
async function runDetect(rec, front, left, right, persist = true) {
|
||||
async function runDetect(rec, front, left, right, persist = true, deferWrinkles = false) {
|
||||
rec.detect_status = '检测中';
|
||||
rec.updated_at = nowIso();
|
||||
const t0 = Date.now();
|
||||
const fpJson = await callFacepp(front, left, right);
|
||||
if (fpJson.result && !fpJson.error_message) {
|
||||
if (fpJson.result && !fpJson.error_message && !deferWrinkles) {
|
||||
fpJson.wrinkle_views = await WrinkleViews.collect(fpJson,{left,right},{
|
||||
key:CRED.key,secret:CRED.secret,url:FACEPP_URL,
|
||||
gapMs:process.env.NODE_ENV==='test'?0:4000,
|
||||
// Keep within the existing 150-second browser timeout, including
|
||||
// upload/serialization headroom. Missing side maps never fail a report.
|
||||
// Legacy admin retries may still collect inline; customer reports use
|
||||
// deferred tasks instead. Missing side maps never fail a report.
|
||||
deadline:t0+120000
|
||||
});
|
||||
}
|
||||
@@ -452,7 +478,7 @@ async function handleAnalyze(req, res) {
|
||||
console.log(`[record] 新检测记录 ${recordId}(${rec.shoot_status},照片${Object.keys(photos).length}/3)`);
|
||||
}
|
||||
|
||||
const fpJson = await runDetect(rec, front, left, right, persist);
|
||||
const fpJson = await runDetect(rec, front, left, right, persist, true);
|
||||
if (persist) updateRecord(rec);
|
||||
|
||||
if (fpJson.error_message) {
|
||||
@@ -484,6 +510,15 @@ async function handleAnalyze(req, res) {
|
||||
side: { left: fpJson.left_side_result || nested.left_side_result || null,
|
||||
right: fpJson.right_side_result || nested.right_side_result || null }
|
||||
};
|
||||
// The main report never waits for display-only side wrinkle requests.
|
||||
if (left || right) {
|
||||
try {
|
||||
payload.wrinkle_job=wrinkleJobs.register(owner,recordId,{primary:{left_side_result:payload.side.left,right_side_result:payload.side.right},photos:{left,right}});
|
||||
payload.wrinkle_views={version:WrinkleViews.VERSION,left:{status:left?'pending':'unavailable'},right:{status:right?'pending':'unavailable'}};
|
||||
rec.wrinkle_view_status={left:{status:left?'pending':'unavailable',error_code:null},right:{status:right?'pending':'unavailable',error_code:null}};
|
||||
if(persist)updateRecord(rec);
|
||||
} catch (_) { /* Optional artwork must never block the main report. */ }
|
||||
}
|
||||
let reportSaved = false, presentation = null, snapshotVm = null;
|
||||
try {
|
||||
snapshotVm = SkinScore.buildViewModel(result, payload.side, scoreProfile(rec));
|
||||
@@ -501,6 +536,7 @@ async function handleAnalyze(req, res) {
|
||||
record_id: recordId, report_saved: reportSaved, presentation, vm: snapshotVm,
|
||||
result,
|
||||
wrinkle_views: payload.wrinkle_views,
|
||||
wrinkle_job: payload.wrinkle_job || null,
|
||||
face_rectangle: fpJson.face_rectangle || null,
|
||||
side: {
|
||||
left: fpJson.left_side_result || nested.left_side_result || null,
|
||||
@@ -876,6 +912,16 @@ async function handleAdmin(req, res, pathname, url) {
|
||||
http.createServer(async (req, res) => {
|
||||
const pathname = req.url.split('?')[0];
|
||||
if (await accounts.route(req, res, pathname)) return;
|
||||
if (req.method==='POST' && pathname==='/api/wrinkle-views') {
|
||||
const owner=accounts.session(req);
|
||||
if(!owner)return sendJson(res,401,{ok:false,message:'请先登录'});
|
||||
if(!accounts.sameOrigin(req))return sendJson(res,403,{ok:false});
|
||||
try {
|
||||
const body=JSON.parse((await readBody(req,4096)).toString('utf8'));
|
||||
const views=await wrinkleJobs.run(owner,body.token);
|
||||
return sendJson(res,views?200:404,views?{ok:true,wrinkle_views:views}:{ok:false,message:'标注任务已失效'});
|
||||
} catch (_) {return sendJson(res,500,{ok:false,message:'侧脸标注暂不可用'});}
|
||||
}
|
||||
if (req.method === 'POST' && pathname === '/api/capture-funnel') {
|
||||
if (!accounts.sameOrigin(req) || !accounts.session(req)) return sendJson(res, 403, { ok: false });
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user