Adapt database connection for local and cloud environments

Update `server/db.ts` to support both Neon serverless and standard PostgreSQL drivers, add database health checks, and improve error logging for database operations.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 55ee188b-6bb4-49b0-8966-1795106363b1
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/C4ZJnmQ
This commit is contained in:
marco370 2025-11-21 16:09:48 +00:00
parent 3076c7946b
commit 42354d5087
5 changed files with 135 additions and 5 deletions

View File

@ -14,6 +14,10 @@ run = ["npm", "run", "start"]
localPort = 5000
externalPort = 80
[[ports]]
localPort = 40859
externalPort = 3001
[[ports]]
localPort = 41303
externalPort = 3002

View File

@ -0,0 +1,70 @@
 VERIFICA SISTEMA:
• Log backend: tail -f /var/log/ids/backend.log
• Log frontend: tail -f /var/log/ids/frontend.log
• API backend: curl http://localhost:8000/health
• Frontend: curl http://localhost:5000
 STATO SERVIZI:
ids 5038 0.2 2.0 1894024 331912 ? Sl 09:20 1:10 /usr/bin/python3.11 main.py
root 10798 0.0 0.1 730192 31688 pts/2 Rl+ 17:01 0:00 /usr/bin/node /usr/bin/npm run dev
[root@ids ids]# sudo -u ids /opt/ids/deployment/restart_all.sh
pkill: killing pid 10842 failed: Operation not permitted
pkill: killing pid 10798 failed: Operation not permitted
[root@ids ids]# curl http://localhost:5000/api/stats
curl http://localhost:5000/api/routers
curl http://localhost:5000/api/detections
{"error":"Failed to fetch stats"}{"error":"Failed to fetch routers"}{"error":"Failed to fetch detections"}[root@ids ids]#
[root@ids ids]# tail -50 /var/log/ids/frontend.log
> NODE_ENV=development tsx server/index.ts
5:00:00 PM [express] serving on port 5000
A PostCSS plugin did not pass the `from` option to `postcss.parse`. This may cause imported assets to be incorrectly transformed. If you've recently added a PostCSS plugin that raised this warning, please contact the package author to fix the issue.
5:00:03 PM [express] GET /api/training-history 500 in 70ms :: {"error":"Failed to fetch training his…
5:00:03 PM [express] GET /api/ml/stats 304 in 70ms :: {"logs":{"total":0,"last_hour":0},"detections"…
5:00:13 PM [express] GET /api/training-history 500 in 5ms :: {"error":"Failed to fetch training hist…
5:00:13 PM [express] GET /api/ml/stats 304 in 17ms :: {"logs":{"total":0,"last_hour":0},"detections"…
5:00:18 PM [express] GET /api/stats 500 in 6ms :: {"error":"Failed to fetch stats"}
5:00:23 PM [express] GET /api/training-history 500 in 6ms :: {"error":"Failed to fetch training hist…
5:00:23 PM [express] GET /api/ml/stats 304 in 18ms :: {"logs":{"total":0,"last_hour":0},"detections"…
5:00:26 PM [express] GET /api/routers 500 in 5ms :: {"error":"Failed to fetch routers"}
5:00:33 PM [express] GET /api/training-history 500 in 5ms :: {"error":"Failed to fetch training hist…
5:00:33 PM [express] GET /api/ml/stats 304 in 17ms :: {"logs":{"total":0,"last_hour":0},"detections"…
5:00:35 PM [express] GET /api/detections 500 in 5ms :: {"error":"Failed to fetch detections"}
5:00:43 PM [express] GET /api/training-history 500 in 5ms :: {"error":"Failed to fetch training hist…
5:00:43 PM [express] GET /api/ml/stats 304 in 17ms :: {"logs":{"total":0,"last_hour":0},"detections"…
5:00:53 PM [express] GET /api/training-history 500 in 5ms :: {"error":"Failed to fetch training hist…
5:00:53 PM [express] GET /api/ml/stats 304 in 16ms :: {"logs":{"total":0,"last_hour":0},"detections"…
[Fri Nov 21 17:01:08 CET 2025] Frontend Node NON attivo, riavvio...
[Fri Nov 21 17:01:10 CET 2025] Frontend riavviato con PID: 10798
> rest-express@1.0.0 dev
> NODE_ENV=development tsx server/index.ts
5:01:12 PM [express] serving on port 5000
A PostCSS plugin did not pass the `from` option to `postcss.parse`. This may cause imported assets to be incorrectly transformed. If you've recently added a PostCSS plugin that raised this warning, please contact the package author to fix the issue.
5:01:15 PM [express] GET /api/training-history 500 in 64ms :: {"error":"Failed to fetch training his…
5:01:15 PM [express] GET /api/ml/stats 304 in 65ms :: {"logs":{"total":0,"last_hour":0},"detections"…
5:01:19 PM [express] GET /api/stats 500 in 10ms :: {"error":"Failed to fetch stats"}
5:01:19 PM [express] GET /api/detections 500 in 7ms :: {"error":"Failed to fetch detections"}
5:01:19 PM [express] GET /api/routers 500 in 6ms :: {"error":"Failed to fetch routers"}
5:01:21 PM [express] GET /api/detections 500 in 4ms :: {"error":"Failed to fetch detections"}
5:01:22 PM [express] GET /api/training-history 500 in 5ms :: {"error":"Failed to fetch training hist…
5:01:23 PM [express] GET /api/ml/stats 304 in 18ms :: {"logs":{"total":0,"last_hour":0},"detections"…
5:01:33 PM [express] GET /api/training-history 500 in 5ms :: {"error":"Failed to fetch training hist…
5:01:33 PM [express] GET /api/ml/stats 304 in 19ms :: {"logs":{"total":0,"last_hour":0},"detections"…
5:01:43 PM [express] GET /api/training-history 500 in 7ms :: {"error":"Failed to fetch training hist…
5:01:43 PM [express] GET /api/ml/stats 304 in 18ms :: {"logs":{"total":0,"last_hour":0},"detections"…
5:01:53 PM [express] GET /api/training-history 500 in 6ms :: {"error":"Failed to fetch training hist…
5:01:53 PM [express] GET /api/ml/stats 304 in 20ms :: {"logs":{"total":0,"last_hour":0},"detections"…
5:02:03 PM [express] GET /api/training-history 500 in 6ms :: {"error":"Failed to fetch training hist…
5:02:03 PM [express] GET /api/ml/stats 304 in 16ms :: {"logs":{"total":0,"last_hour":0},"detections"…
5:02:08 PM [express] GET /api/stats 500 in 5ms :: {"error":"Failed to fetch stats"}
5:02:08 PM [express] GET /api/routers 500 in 4ms :: {"error":"Failed to fetch routers"}
5:02:08 PM [express] GET /api/detections 500 in 3ms :: {"error":"Failed to fetch detections"}
5:02:13 PM [express] GET /api/training-history 500 in 4ms :: {"error":"Failed to fetch training hist…
5:02:13 PM [express] GET /api/ml/stats 304 in 17ms :: {"logs":{"total":0,"last_hour":0},"detections"…
[root@ids ids]#

View File

@ -43,6 +43,25 @@ Sistema di rilevamento intrusioni per router MikroTik basato su Machine Learning
## Fix Recenti (Novembre 2025)
### ✅ Database Driver Fix - Dual Mode Neon/PostgreSQL (21 Nov 2025 - 17:10)
- **Problema**: Frontend Node.js falliva con errore 500 su tutte le query database (`/api/stats`, `/api/routers`, ecc.)
- **Causa ROOT**: `@neondatabase/serverless` usa WebSocket ed è compatibile SOLO con Neon Cloud, non con PostgreSQL locale su AlmaLinux
- **Diagnosi**:
- ✅ DATABASE_URL caricato correttamente (verificato con `psql`)
- ✅ Backend Python funzionava (usa `psycopg2` compatibile con PostgreSQL locale)
- ❌ Backend Node.js falliva (usava `@neondatabase/serverless`)
- **Soluzione**:
- Modificato `server/db.ts` per **dual-mode**:
- Su Replit (Neon Cloud): usa `@neondatabase/serverless` + WebSocket
- Su AlmaLinux (PostgreSQL locale): usa `pg` standard driver
- Auto-detection basata su `DATABASE_URL.includes('neon.tech')`
- Import corretto `pg` per ES modules: `import pg from 'pg'; const { Pool } = pg;`
- Aggiunto health-check database: `SELECT 1` all'avvio
- Aggiunto logging dettagliato errori DB: `[DB ERROR]` prefix
- **Risultato**:
- ✅ Replit: `📦 Using Neon serverless database` + `✅ Database connection successful`
- ⏳ AlmaLinux: `🐘 Using standard PostgreSQL database` (da testare dopo push)
### ✅ Frontend Environment Variables Fix (21 Nov 2025 - 17:00)
- **Problema**: Frontend Node.js non si avviava su server AlmaLinux con errore `DATABASE_URL must be set`
- **Causa 1**: Script `check_frontend.sh` non caricava variabili d'ambiente dal file `.env`

View File

@ -1,9 +1,12 @@
import { Pool, neonConfig } from '@neondatabase/serverless';
import { drizzle } from 'drizzle-orm/neon-serverless';
import { drizzle as drizzleNeon } from 'drizzle-orm/neon-serverless';
import { drizzle as drizzleNode } from 'drizzle-orm/node-postgres';
import { Pool as NeonPool, neonConfig } from '@neondatabase/serverless';
import pg from 'pg';
import type { Pool as PgPoolType } from 'pg';
import ws from "ws";
import * as schema from "@shared/schema";
neonConfig.webSocketConstructor = ws;
const { Pool: PgPool } = pg;
if (!process.env.DATABASE_URL) {
throw new Error(
@ -11,5 +14,34 @@ if (!process.env.DATABASE_URL) {
);
}
export const pool = new Pool({ connectionString: process.env.DATABASE_URL });
export const db = drizzle({ client: pool, schema });
// Check if running on Replit (Neon) or AlmaLinux (PostgreSQL)
const isNeon = process.env.DATABASE_URL.includes('neon.tech') ||
process.env.DATABASE_URL.includes('neon.aws');
let pool: NeonPool | PgPoolType;
let db: ReturnType<typeof drizzleNeon> | ReturnType<typeof drizzleNode>;
if (isNeon) {
// Neon serverless (Replit)
neonConfig.webSocketConstructor = ws;
pool = new NeonPool({ connectionString: process.env.DATABASE_URL });
db = drizzleNeon(pool, { schema });
console.log('📦 Using Neon serverless database');
} else {
// PostgreSQL standard (AlmaLinux)
pool = new PgPool({ connectionString: process.env.DATABASE_URL });
db = drizzleNode(pool, { schema });
console.log('🐘 Using standard PostgreSQL database');
}
// Health check: test database connection on startup
pool.query('SELECT 1')
.then(() => console.log('✅ Database connection successful'))
.catch((err) => {
console.error('❌ Database connection failed:', err.message);
// Mask entire connection string for security
const dbType = isNeon ? 'Neon Cloud' : 'PostgreSQL';
console.error(`Database type: ${dbType}`);
});
export { pool, db };

View File

@ -10,6 +10,7 @@ export async function registerRoutes(app: Express): Promise<Server> {
const routers = await storage.getAllRouters();
res.json(routers);
} catch (error) {
console.error('[DB ERROR] Failed to fetch routers:', error);
res.status(500).json({ error: "Failed to fetch routers" });
}
});
@ -64,6 +65,7 @@ export async function registerRoutes(app: Express): Promise<Server> {
const detections = await storage.getAllDetections(limit);
res.json(detections);
} catch (error) {
console.error('[DB ERROR] Failed to fetch detections:', error);
res.status(500).json({ error: "Failed to fetch detections" });
}
});
@ -83,6 +85,7 @@ export async function registerRoutes(app: Express): Promise<Server> {
const whitelist = await storage.getAllWhitelist();
res.json(whitelist);
} catch (error) {
console.error('[DB ERROR] Failed to fetch whitelist:', error);
res.status(500).json({ error: "Failed to fetch whitelist" });
}
});
@ -116,6 +119,7 @@ export async function registerRoutes(app: Express): Promise<Server> {
const history = await storage.getTrainingHistory(limit);
res.json(history);
} catch (error) {
console.error('[DB ERROR] Failed to fetch training history:', error);
res.status(500).json({ error: "Failed to fetch training history" });
}
});
@ -162,6 +166,7 @@ export async function registerRoutes(app: Express): Promise<Server> {
latestTraining: latestTraining
});
} catch (error) {
console.error('[DB ERROR] Failed to fetch stats:', error);
res.status(500).json({ error: "Failed to fetch stats" });
}
});