Files
claudetools/projects/dataforth-dos/testdatadb-fix/server.js
Mike Swanson 470638ff86 sync: Dataforth sync fixes, TestDataDB stability, and client scripts
Dataforth DOS:
- TestDataDB: singleton DB connection fix (crash prevention), WAL mode,
  WinSW service config, backup script, uncaught exception handlers
- Sync-FromNAS.ps1: Get-NASFileList temp file approach to avoid SSH
  stdout deadlock, *> $null output suppression, 8.3 filename filter
  for PUSH phase, backslash-escaped SCP paths, rename-to-.synced
- import.js: INSERT OR REPLACE for re-tested devices
- Full import run: 1,028,275 -> 1,632,793 records, indexes added
- Deploy script for sync fixes to AD2

Client scripts (temp/):
- BG Builders: Lesley account check, MFA phone update
- Lonestar Electrical: Kyla/Russ Google Workspace setup, 2FA bypass
- AD2 diagnostics and NAS connectivity tests

PENDING: Investigate why newest test_date is Jan 19 despite daily tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 06:08:31 -07:00

104 lines
3.7 KiB
JavaScript

/**
* Test Data Database Server
* Express.js server with search API and web interface
*
* Fixed version - singleton DB connection, crash resilience,
* graceful shutdown, request logging.
*/
const express = require('express');
const cors = require('cors');
const path = require('path');
const apiRoutes = require('./routes/api');
const { cleanup } = require('./routes/api');
const app = express();
const PORT = process.env.PORT || 3000;
const HOST = '0.0.0.0';
// ---------------------------------------------------------------------------
// Crash resilience - log and continue rather than dying
// ---------------------------------------------------------------------------
process.on('uncaughtException', (err) => {
console.error(`[${new Date().toISOString()}] [UNCAUGHT EXCEPTION] ${err.stack || err.message}`);
});
process.on('unhandledRejection', (reason) => {
console.error(`[${new Date().toISOString()}] [UNHANDLED REJECTION] ${reason}`);
});
// ---------------------------------------------------------------------------
// Middleware
// ---------------------------------------------------------------------------
app.use(cors());
app.use(express.json());
app.use(express.static(path.join(__dirname, 'public')));
// Request logging
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
console.log(
`[${new Date().toISOString()}] ${req.method} ${req.originalUrl} ${res.statusCode} ${duration}ms`
);
});
next();
});
// ---------------------------------------------------------------------------
// Routes
// ---------------------------------------------------------------------------
app.use('/api', apiRoutes);
// Serve index.html for root
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
// ---------------------------------------------------------------------------
// Start server
// ---------------------------------------------------------------------------
const server = app.listen(PORT, HOST, () => {
console.log(`\n========================================`);
console.log(`Test Data Database Server`);
console.log(`========================================`);
console.log(`Server running on all interfaces (${HOST}:${PORT})`);
console.log(`Local: http://localhost:${PORT}`);
console.log(`LAN: http://192.168.0.6:${PORT}`);
console.log(`API endpoints:`);
console.log(` GET /api/search?serial=...&model=...`);
console.log(` GET /api/record/:id`);
console.log(` GET /api/datasheet/:id`);
console.log(` GET /api/stats`);
console.log(` GET /api/filters`);
console.log(` GET /api/export?format=csv&...`);
console.log(`========================================\n`);
});
// ---------------------------------------------------------------------------
// Graceful shutdown
// ---------------------------------------------------------------------------
function shutdown(signal) {
console.log(`\n[${new Date().toISOString()}] Received ${signal}. Shutting down gracefully...`);
server.close(() => {
console.log(`[${new Date().toISOString()}] HTTP server closed.`);
cleanup();
console.log(`[${new Date().toISOString()}] Database connection closed. Goodbye.`);
process.exit(0);
});
// Force exit after 10 seconds if graceful shutdown stalls
setTimeout(() => {
console.error(`[${new Date().toISOString()}] Forced shutdown after timeout.`);
cleanup();
process.exit(1);
}, 10000);
}
process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('SIGINT', () => shutdown('SIGINT'));
module.exports = app;