Update matcher binary path to /app/bin/face_matcher in configuration and documentation
All checks were successful
Publish FaceAI Container / publish (push) Successful in 2m53s

This commit is contained in:
MaddoScientisto 2026-04-19 11:38:09 +02:00
commit c0732c142c
7 changed files with 76 additions and 8 deletions

View file

@ -13,7 +13,7 @@ FACEAI_RUNTIME_ROOT=/data/runtime
FACEAI_UPLOAD_ROOT=/data/runtime/uploads
FACEAI_LOG_ROOT=/data/logs
FACEAI_PKL_ROOT=/data/pkl
FACEAI_MATCHER_BINARY=/opt/face-recognition/face_matcher
FACEAI_MATCHER_BINARY=/app/bin/face_matcher
LIVE_SITE_BASE_URL=https://www.regalamiunsorriso.it
LIVE_SITE_LOGIN_URL=https://www.regalamiunsorriso.it/login_clienti-it.html
LIVE_SITE_RACE_URL=https://www.regalamiunsorriso.it/42%20HALF%20MARATHON%20FIRENZE_gara-1018545---96-1.html

View file

@ -384,7 +384,7 @@ Processor settings:
| Variable | Required | Example | Purpose |
| --- | --- | --- | --- |
| `FACEAI_PKL_ROOT` | yes | `/data/pkl` | mounted race-to-PKL dataset root |
| `FACEAI_MATCHER_BINARY` | yes | `/opt/face-recognition/face_matcher` | matcher executable baked into the processor image |
| `FACEAI_MATCHER_BINARY` | yes | `/app/bin/face_matcher` | matcher executable baked into the processor image |
| `FACEAI_WORKER_CONCURRENCY` | optional | `2` | BullMQ worker concurrency |
| `FACEAI_WORKER_TIMEOUT_MS` | optional | `300000` | matcher timeout in milliseconds |

View file

@ -60,6 +60,35 @@ app.use(cors({
credentials: true
}));
function summarizeRace(race) {
return {
id: race?.id || null,
name: race?.name || null,
storage: race?.storage || null
};
}
function summarizeUser(user) {
return {
id: user?.id || null,
displayName: user?.displayName || null,
membershipStatus: user?.membershipStatus || null
};
}
function clientIp(req) {
const forwardedFor = String(req.headers['x-forwarded-for'] || '').split(',')[0].trim();
return forwardedFor || req.ip || req.socket?.remoteAddress || null;
}
function logFaceAiAccess(event, req, details = {}) {
console.log(`[FaceAI] ${event} ${JSON.stringify({
ip: clientIp(req),
userAgent: req.headers['user-agent'] || null,
...details
})}`);
}
function getFaceAiSession(req) {
const sessionId = req.cookies[config.sessionCookieName];
return sessionId ? getSession(sessionId) : null;
@ -318,6 +347,15 @@ app.post('/api/auth/exchange', async (req, res) => {
}
});
logFaceAiAccess('Session exchange', req, {
sessionId,
user: summarizeUser(payload.user),
race: summarizeRace(race),
lang: payload.lang,
availability,
returnUrl: payload.returnUrl
});
res.cookie(config.sessionCookieName, sessionId, {
httpOnly: true,
sameSite: 'lax',
@ -341,6 +379,13 @@ app.post('/api/auth/exchange', async (req, res) => {
});
app.get('/api/session', requireSession, (req, res) => {
logFaceAiAccess('Session viewed', req, {
sessionId: req.cookies[config.sessionCookieName] || null,
user: summarizeUser(req.faceaiSession.user),
race: summarizeRace(req.faceaiSession.race),
lang: req.faceaiSession.lang,
availability: req.faceaiSession.availability || null
});
res.json(req.faceaiSession);
});
@ -420,6 +465,16 @@ app.post('/api/searches', requireSession, enforceSearchRateLimit, upload.single(
removeOnFail: 100
});
logFaceAiAccess('Identification requested', req, {
searchId: updatedSearch.id,
user: summarizeUser(req.faceaiSession.user),
race: summarizeRace(race),
lang: req.faceaiSession.lang,
selfieName: updatedSearch.selfieName,
uploadPath: updatedSearch.uploadPath,
availability
});
res.status(201).json({
id: updatedSearch.id,
status: updatedSearch.status,
@ -476,8 +531,19 @@ app.get('/api/searches/:id/redirect', requireSession, async (req, res) => {
const token = issueReturnToken(result);
const redirectUrl = `${config.legacyReturnUrl}?resultId=${encodeURIComponent(result.id)}&token=${encodeURIComponent(token)}`;
logFaceAiAccess('Identification redirect issued', req, {
searchId: search.id,
resultId: result.id,
user: summarizeUser(req.faceaiSession.user),
race: summarizeRace(req.faceaiSession.race),
matchCount: result.matches?.length || 0,
redirectUrl
});
res.json({
url: `${config.legacyReturnUrl}?resultId=${encodeURIComponent(result.id)}&token=${encodeURIComponent(token)}`
url: redirectUrl
});
});

View file

@ -8,7 +8,7 @@ export const config = {
runtimeRoot: process.env.FACEAI_RUNTIME_ROOT || '/data/runtime',
logRoot: process.env.FACEAI_LOG_ROOT || path.join(process.env.FACEAI_RUNTIME_ROOT || '/data/runtime', 'logs'),
pklRoot: process.env.FACEAI_PKL_ROOT || '/data/pkl',
matcherBinary: process.env.FACEAI_MATCHER_BINARY || '/opt/face-recognition/face_matcher',
matcherBinary: process.env.FACEAI_MATCHER_BINARY || '/app/bin/face_matcher',
searchTtlSeconds: Number(process.env.FACEAI_SEARCH_TTL_SECONDS || 24 * 60 * 60),
resultTtlSeconds: Number(process.env.FACEAI_RESULT_TTL_SECONDS || 24 * 60 * 60)
};

View file

@ -32,6 +32,8 @@ async function ensureMatcherBinaryAvailable() {
}
}
console.log(`FaceAI processor configured matcher binary: ${config.matcherBinary}`);
function formatLogLine(message, details) {
const timestamp = new Date().toISOString();
if (details === undefined) {

View file

@ -70,7 +70,7 @@ services:
FACEAI_LOG_ROOT: /data/logs
FACEAI_PKL_ROOT: /data/pkl
FACEAI_WORKER_CONCURRENCY: 2
FACEAI_MATCHER_BINARY: /opt/face-recognition/face_matcher
FACEAI_MATCHER_BINARY: /app/bin/face_matcher
volumes:
- .:/app
- ./logs:/data/logs

View file

@ -8,8 +8,8 @@ RUN apt-get update \
WORKDIR /app
COPY faceai /app
COPY bin/Face_Recognition_Unix/face_matcher /opt/face-recognition/face_matcher
COPY bin/Face_Recognition_Unix/face_matcher /app/bin/face_matcher
RUN chmod +x /opt/face-recognition/face_matcher
RUN chmod +x /app/bin/face_matcher
ENV FACEAI_MATCHER_BINARY=/opt/face-recognition/face_matcher
ENV FACEAI_MATCHER_BINARY=/app/bin/face_matcher