Files
yourpart3/backend/scripts/falukant-town-product-worth-stats.mjs

104 lines
3.9 KiB
JavaScript

#!/usr/bin/env node
/**
* Liest backend/sql/diagnostics/falukant_town_product_worth_stats.sql und gibt eine Tabelle aus.
*
* cd backend && npm run diag:town-worth
*
* SSH-Tunnel: DB_HOST=127.0.0.1, DB_PORT=<lokaler Forward, z. B. 60000> — siehe backend/env.example
* Hängt die Verbindung: Tunnel läuft? Sonst TLS (DB_SSL=1), falscher Port, Firewall.
*/
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
const __dirname = dirname(fileURLToPath(import.meta.url));
const sqlPath = join(__dirname, '../sql/diagnostics/falukant_town_product_worth_stats.sql');
const QUERY_TIMEOUT_MS = Number.parseInt(process.env.DIAG_QUERY_TIMEOUT_MS || '60000', 10);
const AUTH_TIMEOUT_MS = Number.parseInt(process.env.DIAG_AUTH_TIMEOUT_MS || '25000', 10);
process.env.QUIET_ENV_LOGS = process.env.QUIET_ENV_LOGS || '1';
process.env.DOTENV_CONFIG_QUIET = process.env.DOTENV_CONFIG_QUIET || '1';
if (!process.env.DB_CONNECT_TIMEOUT_MS) {
process.env.DB_CONNECT_TIMEOUT_MS = '15000';
}
await import('../config/loadEnv.js');
const { sequelize } = await import('../utils/sequelize.js');
/** Promise.race + Timeout, aber Timer wird bei Erfolg cleared — sonst blockiert setTimeout(60s) den Prozess. */
function withTimeout(promise, ms, onTimeoutError) {
let timerId;
const timeoutPromise = new Promise((_, reject) => {
timerId = setTimeout(() => reject(new Error(onTimeoutError)), ms);
});
return Promise.race([promise, timeoutPromise]).finally(() => {
clearTimeout(timerId);
});
}
function raceQuery(sql) {
return withTimeout(
sequelize.query(sql),
QUERY_TIMEOUT_MS,
`Abfrage-Timeout nach ${QUERY_TIMEOUT_MS} ms (DIAG_QUERY_TIMEOUT_MS)`
);
}
function raceAuth() {
return withTimeout(
sequelize.authenticate(),
AUTH_TIMEOUT_MS,
`authenticate() Timeout nach ${AUTH_TIMEOUT_MS} ms — TCP/TLS zu PostgreSQL kommt nicht zustande (DIAG_AUTH_TIMEOUT_MS).`
);
}
function printConnectionHints() {
const port = process.env.DB_PORT || '5432';
const host = process.env.DB_HOST || '?';
const local = host === '127.0.0.1' || host === 'localhost' || host === '::1';
console.error('');
console.error('[diag] Mögliche Ursachen:');
if (local) {
console.error(' • SSH-Tunnel: Läuft z. B. ssh -L ' + port + ':127.0.0.1:5432 …? Dann DB_HOST=127.0.0.1 DB_PORT=' + port + ' (DB_SSL meist aus).');
console.error(' • Falscher lokaler Forward-Port in .env (DB_PORT).');
} else {
console.error(' • PostgreSQL erwartet TLS: in .env DB_SSL=1 setzen (ggf. DB_SSL_REJECT_UNAUTHORIZED=0 bei selbstsigniert).');
console.error(' • Falscher Port: DB_PORT=' + port + ' prüfen.');
console.error(' • Server-Firewall: deine IP muss für Port', port, 'auf', host, 'freigeschaltet sein.');
}
console.error(' • Test: nc -zv', host, port);
console.error('');
}
try {
const sql = readFileSync(sqlPath, 'utf8');
const host = process.env.DB_HOST || '(unbekannt)';
const t0 = Date.now();
console.log('');
console.log('[diag] PostgreSQL: authenticate() … (Host:', host + ', Port:', process.env.DB_PORT || '5432', ', DB_SSL:', process.env.DB_SSL === '1' ? '1' : '0', ')');
console.log('');
await raceAuth();
console.log('[diag] authenticate() ok nach', Date.now() - t0, 'ms');
await sequelize.query("SET statement_timeout = '30s'");
const t1 = Date.now();
const [rows] = await raceQuery(sql);
console.log('[diag] SELECT ok nach', Date.now() - t1, 'ms (gesamt', Date.now() - t0, 'ms)');
console.log('');
console.table(rows);
await sequelize.close();
process.exit(0);
} catch (err) {
console.error(err.message || err);
printConnectionHints();
try {
await sequelize.close();
} catch (_) {}
process.exit(1);
}