Refactor FaceAI build process and update Docker configurations to include matcher binary

This commit is contained in:
MaddoScientisto 2026-04-19 11:00:50 +02:00
commit d36b0f4e46
15 changed files with 177 additions and 30 deletions

View file

@ -117,7 +117,10 @@ const emit = defineEmits([
<div class="faceai-dropzone-inner">
<div class="faceai-dropzone-icon">
<i class="fa fa-cloud-upload" aria-hidden="true"></i>
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="M12.75 3.75a.75.75 0 0 0-1.5 0v8.69L8.78 9.97a.75.75 0 1 0-1.06 1.06l3.75 3.75a.75.75 0 0 0 1.06 0l3.75-3.75a.75.75 0 1 0-1.06-1.06l-2.47 2.47V3.75Z" fill="currentColor" />
<path d="M5.25 15a3 3 0 0 0 .28 6h12.94a3.53 3.53 0 0 0 .27-7.04 5.75 5.75 0 0 0-11.17-1.48A3.75 3.75 0 0 0 5.25 15Zm1.5 0c0-.87.35-1.65.92-2.22a.75.75 0 0 0 .18-.77 4.25 4.25 0 0 1 8.29 1.39v.25a.75.75 0 0 0 .75.75h1.58a2.03 2.03 0 0 1 0 4.06H5.53A1.5 1.5 0 1 1 5.53 15h1.22Z" fill="currentColor" />
</svg>
</div>
<template v-if="selectedFile">
@ -290,6 +293,11 @@ const emit = defineEmits([
box-shadow: inset 0 0 0 1px rgba(191, 158, 117, 0.24);
}
.faceai-dropzone-icon svg {
width: 44px;
height: 44px;
}
.faceai-dropzone-title {
font-size: 1.2rem;
font-weight: 700;

View file

@ -64,7 +64,12 @@ function closeMenu() {
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link active" href="#" @click="closeMenu">
<i class="fa fa-user" aria-hidden="true"></i> Il mio account
<span class="faceai-inline-icon" aria-hidden="true">
<svg viewBox="0 0 24 24" focusable="false">
<path d="M12 12.5a4.25 4.25 0 1 0 0-8.5 4.25 4.25 0 0 0 0 8.5Zm0 2.25c-4.48 0-8.25 2.18-8.25 4.75 0 .28.22.5.5.5h15.5a.5.5 0 0 0 .5-.5c0-2.57-3.77-4.75-8.25-4.75Z" fill="currentColor" />
</svg>
</span>
Il mio account
</a>
</li>
<li class="nav-item">
@ -78,3 +83,18 @@ function closeMenu() {
</nav>
</div>
</template>
<style scoped>
.faceai-inline-icon {
display: inline-flex;
width: 1rem;
height: 1rem;
margin-right: 0.35rem;
vertical-align: text-bottom;
}
.faceai-inline-icon svg {
width: 100%;
height: 100%;
}
</style>

View file

@ -36,7 +36,6 @@ export function legacyAsset(path) {
export function injectLegacyStylesheets() {
const stylesheets = [
legacyAsset('/vendor/bootstrap/css/bootstrap.min.css'),
legacyAsset('/css/font-awesome.min.css'),
'https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i',
legacyAsset('/css/custom-style.css')
];

View file

@ -40,6 +40,10 @@ export async function runFaceMatcher({ matcherBinary, selfiePath, pklPath, csvPa
child.on('error', (error) => {
clearTimeout(timer);
if (error?.code === 'ENOENT') {
reject(new Error(`face_matcher not found at ${matcherBinary}. Check FACEAI_MATCHER_BINARY and the processor bind mount.`));
return;
}
reject(error);
});

View file

@ -1,3 +1,4 @@
import { constants as fsConstants } from 'node:fs';
import fs from 'node:fs/promises';
import path from 'node:path';
import { Worker } from 'bullmq';
@ -15,6 +16,22 @@ import { parseMatcherCsv, resolvePklPath, runFaceMatcher } from './worker-utils.
const connection = createRedisConnection(config.redisUrl);
async function ensureMatcherBinaryAvailable() {
try {
await fs.access(config.matcherBinary, fsConstants.X_OK);
} catch (error) {
console.error(`FaceAI processor cannot start because the matcher binary is unavailable: ${config.matcherBinary}`);
console.error('Ensure FACEAI_MATCHER_BINARY points to a real executable and that the processor bind mount contains face_matcher.');
if (error?.code === 'ENOENT') {
console.error('The configured matcher path does not exist inside the processor runtime.');
} else if (error?.code === 'EACCES') {
console.error('The configured matcher path exists but is not executable by the processor runtime.');
}
throw error;
}
}
function formatLogLine(message, details) {
const timestamp = new Date().toISOString();
if (details === undefined) {
@ -147,6 +164,8 @@ async function processJob(job) {
}
}
await ensureMatcherBinaryAvailable();
const worker = new Worker(config.queueName, processJob, {
connection,
concurrency: config.workerConcurrency