142 lines
2.4 KiB
JavaScript
142 lines
2.4 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const db = require('../db/knex');
|
|
|
|
const LOCK_PATH = path.resolve(
|
|
__dirname,
|
|
'..',
|
|
'face-scan-daemon.lock',
|
|
);
|
|
|
|
function readLock() {
|
|
try {
|
|
const text = fs.readFileSync(
|
|
LOCK_PATH,
|
|
'utf8',
|
|
);
|
|
|
|
return JSON.parse(text);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function isProcessAlive(pidValue) {
|
|
const pid = Number(pidValue);
|
|
|
|
if (
|
|
!Number.isInteger(pid)
|
|
|| pid <= 0
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
process.kill(pid, 0);
|
|
return true;
|
|
} catch (error) {
|
|
return error.code === 'EPERM';
|
|
}
|
|
}
|
|
|
|
async function getQueueStatus() {
|
|
const rows = await db('face_scan_jobs')
|
|
.select('status')
|
|
.count({ count: '*' })
|
|
.groupBy('status');
|
|
|
|
const queue = {
|
|
pending: 0,
|
|
processing: 0,
|
|
done: 0,
|
|
error: 0,
|
|
};
|
|
|
|
for (const row of rows) {
|
|
queue[row.status] =
|
|
Number(row.count || 0);
|
|
}
|
|
|
|
return queue;
|
|
}
|
|
|
|
async function getFaceStatistics() {
|
|
const row = await db('face_scan_jobs')
|
|
.select(
|
|
db.raw(
|
|
'SUM(COALESCE(faces_detected, 0)) '
|
|
+ 'AS total_faces',
|
|
),
|
|
db.raw(
|
|
'SUM(attempts) AS total_attempts',
|
|
),
|
|
db.raw(
|
|
'ROUND(AVG(execution_ms), 1) '
|
|
+ 'AS average_execution_ms',
|
|
),
|
|
)
|
|
.first();
|
|
|
|
return {
|
|
total_faces:
|
|
Number(row?.total_faces || 0),
|
|
|
|
total_attempts:
|
|
Number(row?.total_attempts || 0),
|
|
|
|
average_execution_ms:
|
|
row?.average_execution_ms == null
|
|
? null
|
|
: Number(row.average_execution_ms),
|
|
};
|
|
}
|
|
|
|
async function main() {
|
|
const queue = await getQueueStatus();
|
|
const statistics =
|
|
await getFaceStatistics();
|
|
|
|
const lock = readLock();
|
|
const daemonAlive =
|
|
lock != null
|
|
&& isProcessAlive(lock.pid);
|
|
|
|
const result = {
|
|
daemon: {
|
|
running: daemonAlive,
|
|
lock_exists: lock != null,
|
|
lock_path: LOCK_PATH,
|
|
pid: lock?.pid ?? null,
|
|
started_at:
|
|
lock?.started_at ?? null,
|
|
project_root:
|
|
lock?.project_root ?? null,
|
|
stale_lock:
|
|
lock != null && !daemonAlive,
|
|
},
|
|
|
|
queue,
|
|
|
|
statistics,
|
|
};
|
|
|
|
console.log(
|
|
JSON.stringify(result, null, 2),
|
|
);
|
|
}
|
|
|
|
main()
|
|
.catch((error) => {
|
|
console.error(
|
|
'[faceScanStatus] errore:',
|
|
error.stack
|
|
|| error.message
|
|
|| error,
|
|
);
|
|
|
|
process.exitCode = 1;
|
|
})
|
|
.finally(async () => {
|
|
await db.destroy();
|
|
});
|