Files
picpeak/backend/src/services/workerManager.js
T
Paul Nothaft 9143997f8e style(backend): clear the eslint backlog to zero
929 problems (928 errors, 1 warning) -> 0, exit 0.

Rule breakdown, which corrects the report's premise -- `indent` dominated, not
`quotes`: indent 719, quotes 68, no-unused-vars 54, no-empty 36,
no-useless-escape 22, no-case-declarations 17, no-inner-declarations 6,
no-control-regex 5, no-useless-catch 1, no-console 1 (warn).

--fix handled only indent + quotes (719+68 = exactly the "fixable" count).
no-useless-escape was NOT auto-fixable in this eslint version, so the one
genuinely risky class never went through the autofixer -- all 22 were done by
hand. Two mechanical proofs on the autofix diff: a token-level AST diff
(espree, before vs after) shows exactly 68 differing tokens, all quotes, with
the 719 indent fixes producing zero token changes; and a cooked-value diff of
every string/template/regex literal shows 0 differences.

Regex escapes: eslint was correctly conservative and did not flag the
load-bearing ones -- \- in [^a-zA-Z0-9_\-\.] (unescaping makes an invalid
reversed _ -> . range) or in [!@#$%^&*()_+\-=...] (would become a + -> = range
silently matching ",-."). Every removal was a \/ \[ or \. inside a character
class; all 11 old/new pairs were brute-forced over 794 inputs with 0
mismatches.

Manual fixes: no-empty were all deliberate best-effort catches around activity
logging, annotated rather than restructured; no-case-declarations braced in
two adminBackup switches; no-inner-declarations converted to const arrows
after checking no call precedes the declaration and no this/arguments use;
no-control-regex and no-console got targeted disables with stated reasons;
one `catch (e) { throw e; }` wrapper removed.

Two unused bindings were near-misses worth noting: secureStatic.js's
`fullPath` is a path-traversal guard (safePathJoin throws on escape) and
restoreService.js's `backupManifest` is the throw-on-corrupt-manifest gate
before a rollback -- deleting either would have silently removed a check. Only
the bindings were dropped; the calls stay.

Two real bugs found and deliberately preserved with a comment plus a narrow
disable rather than deleted, since deleting would erase the evidence:
_workflowSeedBoot.js's `booted` is written but never read, so the intended
once-per-process guard is missing its early return and workflows re-seed on
every call; and quoteService.js's VALID_QUOTE_TRANSITIONS is a full state
machine nothing consults, so quote status changes are unvalidated.

Backend test suite: 253 suites / 2552 tests passing, 0 failures, before and
after.

Refs testplan REPORT.md #22 (Part 1.2.02).
2026-09-01 16:46:34 +02:00

73 lines
1.9 KiB
JavaScript

/**
* Worker Manager - Background service for PicPeak
*
* This service runs as a separate process to handle:
* - File watching for new photos
* - Expiration checking for events
* - Other background tasks
*/
const path = require('path');
const logger = require('../utils/logger');
// Load environment variables
require('dotenv').config({ path: path.join(__dirname, '../../.env') });
// Import services
const { startFileWatcher } = require('./fileWatcher');
const { startExpirationChecker } = require('./expirationChecker');
let isShuttingDown = false;
async function startWorkers() {
logger.info('Starting PicPeak background workers...');
try {
// Start file watcher for automatic photo processing
startFileWatcher();
logger.info('File watcher started successfully');
// Start expiration checker for event lifecycle management
startExpirationChecker();
logger.info('Expiration checker started successfully');
logger.info('All background workers started successfully');
} catch (error) {
logger.error('Failed to start background workers:', error);
process.exit(1);
}
}
function handleShutdown(signal) {
if (isShuttingDown) {
logger.info('Shutdown already in progress...');
return;
}
isShuttingDown = true;
logger.info(`Received ${signal}. Shutting down gracefully...`);
// Give time for cleanup
setTimeout(() => {
logger.info('Worker manager shutdown complete');
process.exit(0);
}, 1000);
}
// Handle shutdown signals
process.on('SIGTERM', () => handleShutdown('SIGTERM'));
process.on('SIGINT', () => handleShutdown('SIGINT'));
// Handle uncaught errors
process.on('uncaughtException', (error) => {
logger.error('Uncaught exception in worker manager:', error);
process.exit(1);
});
process.on('unhandledRejection', (reason) => {
logger.error('Unhandled rejection in worker manager:', reason);
});
// Start workers
startWorkers();