104 lines
3.9 KiB
JavaScript
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);
|
|
}
|