From bba8026b7c237eb1d6c094662a175d14a5f1fc7a Mon Sep 17 00:00:00 2001 From: MaddoScientisto Date: Sun, 19 Apr 2026 14:18:00 +0200 Subject: [PATCH] feat: Enhance FaceAI functionality and improve login process - Added a retry mechanism for page navigation in `live-site-test-utils.js` to handle transient errors during login. - Introduced a new function `performLiveLoginRequest` to handle login requests via API, improving the login flow. - Updated the login process to utilize the new API request method, ensuring a more robust authentication. - Implemented new utility functions in `rus-ecom-240621.js` for managing FaceAI state and filtering. - Created `faceai_photo_lookup.jsp` to handle photo lookups, returning JSON responses for better integration with the frontend. - Updated `faceai_return.php` to redirect users with appropriate parameters after FaceAI processing. - Modified `fotoCR.jsp` and `fotoCR-en.jsp` to include FaceAI photo IDs in the image elements for better tracking. - Enhanced the UI to display the number of matched photos dynamically based on FaceAI results. --- faceai/apps/backend/src/config.js | 4 +- faceai/apps/backend/src/server.js | 29 +- .../src/components/FaceAiUploadPanel.vue | 24 +- .../frontend/src/composables/useFaceAiHome.js | 33 +- faceai/apps/processor/src/config.js | 2 +- faceai/playwright.config.js | 4 +- faceai/playwright.live.config.js | 4 +- faceai/tests/e2e/faceai-simulator.spec.js | 88 +++- faceai/tests/live-site/auth.setup.js | 8 +- faceai/tests/live-site/live-race.spec.js | 118 ++++- .../tests/live-site/live-site-test-utils.js | 56 ++- sync/www-deploy-manifest.md | 7 +- www/_js/rus-ecom-240621.js | 436 +++++++++++++++++- www/faceai_photo_lookup.jsp | 299 ++++++++++++ www/faceai_return.php | 42 +- www/fotoCR-en.jsp | 8 +- www/fotoCR.jsp | 8 +- 17 files changed, 1076 insertions(+), 94 deletions(-) create mode 100644 www/faceai_photo_lookup.jsp diff --git a/faceai/apps/backend/src/config.js b/faceai/apps/backend/src/config.js index 6b43c1e2..bc5c1ecd 100644 --- a/faceai/apps/backend/src/config.js +++ b/faceai/apps/backend/src/config.js @@ -28,7 +28,7 @@ export const config = { uploadRoot: process.env.FACEAI_UPLOAD_ROOT || path.join(process.env.FACEAI_RUNTIME_ROOT || '/data/runtime', 'uploads'), searchTtlSeconds: Number(process.env.FACEAI_SEARCH_TTL_SECONDS || 24 * 60 * 60), resultTtlSeconds: Number(process.env.FACEAI_RESULT_TTL_SECONDS || 24 * 60 * 60), - processorHeartbeatGraceMs: Number(process.env.FACEAI_PROCESSOR_HEARTBEAT_GRACE_MS || 20 * 1000), + processorHeartbeatGraceMs: Number(process.env.FACEAI_PROCESSOR_HEARTBEAT_GRACE_MS || 60 * 1000), rateLimitWindowSeconds: Number(process.env.FACEAI_RATE_LIMIT_WINDOW_SECONDS || 10 * 60), - rateLimitMaxRequests: Number(process.env.FACEAI_RATE_LIMIT_MAX_REQUESTS || 5) + rateLimitMaxRequests: Number(process.env.FACEAI_RATE_LIMIT_MAX_REQUESTS || 20) }; diff --git a/faceai/apps/backend/src/server.js b/faceai/apps/backend/src/server.js index 15c31f41..891e165d 100644 --- a/faceai/apps/backend/src/server.js +++ b/faceai/apps/backend/src/server.js @@ -20,6 +20,7 @@ import { getSearchRecord, incrementRateLimit, markSearchFailed, + releaseActiveSearchLock, saveSearchRecord } from './redis-store.js'; import { getSearchQueue } from './queue.js'; @@ -126,6 +127,27 @@ async function failSearchIfProcessorUnavailable(search) { ); } +async function resolveBlockingActiveSearch(userId) { + const activeSearchId = await getActiveSearchId(redis, userId); + if (!activeSearchId) { + return null; + } + + const existingSearch = await getSearchRecord(redis, activeSearchId); + if (!existingSearch) { + await releaseActiveSearchLock(redis, userId, activeSearchId); + return null; + } + + const normalizedSearch = await failSearchIfProcessorUnavailable(existingSearch); + if (!normalizedSearch || normalizedSearch.status === 'completed' || normalizedSearch.status === 'failed') { + await releaseActiveSearchLock(redis, userId, activeSearchId); + return null; + } + + return normalizedSearch; +} + function logHealthFailure(details) { const signature = JSON.stringify(details); if (signature === lastHealthFailureSignature) { @@ -528,13 +550,14 @@ app.post('/api/searches', requireSession, enforceSearchRateLimit, upload.single( return; } - const activeSearchId = await getActiveSearchId(redis, userId); + const activeSearch = await resolveBlockingActiveSearch(userId); - if (activeSearchId) { + if (activeSearch) { res.status(409).json({ error: 'There is already an operation being processed.', code: 'ACTIVE_SEARCH_EXISTS', - activeSearchId + activeSearchId: activeSearch.id, + activeSearchStatus: activeSearch.status }); return; } diff --git a/faceai/apps/frontend/src/components/FaceAiUploadPanel.vue b/faceai/apps/frontend/src/components/FaceAiUploadPanel.vue index 19f21986..793214cc 100644 --- a/faceai/apps/frontend/src/components/FaceAiUploadPanel.vue +++ b/faceai/apps/frontend/src/components/FaceAiUploadPanel.vue @@ -1,5 +1,7 @@