Configure production database connection for increased reliability

Updates the server-side database configuration to use standard PostgreSQL for production environments, ensuring a more robust and reliable connection. Previously, it might have defaulted to a different setup or encountered connection issues.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: d396e5bd-e32d-4a20-9e7d-71e7102ddc6c
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/d396e5bd-e32d-4a20-9e7d-71e7102ddc6c/CrwFq15
This commit is contained in:
michaelschal committed 2025-08-11 15:12:54 +00:00
1 parent 2aecaa2672
commit 22a6c5d7f6
6 files changed
+305 -15

No files matched your search

@@ -0,0 +1,199 @@
status: 500,
message: 'connect ECONNREFUSED 172.20.0.10:443',
error: ErrorEvent {
[Symbol(kTarget)]: WebSocket {
_events: [Object: null prototype],
_eventsCount: 4,
_maxListeners: undefined,
_binaryType: 'arraybuffer',
_closeCode: 1006,
_closeFrameReceived: false,
_closeFrameSent: false,
_closeMessage: <Buffer >,
_closeTimer: null,
_errorEmitted: true,
_extensions: {},
_paused: false,
_protocol: '',
_readyState: 3,
_receiver: null,
_sender: null,
_socket: null,
_bufferedAmount: 0,
_isServer: false,
_redirects: 0,
_autoPong: true,
_url: 'wss://logiflow-db/v2',
_req: null,
[Symbol(shapeMode)]: false,
[Symbol(kCapture)]: false
},
[Symbol(kType)]: 'error',
[Symbol(kError)]: Error: connect ECONNREFUSED 172.20.0.10:443
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1611:16) {
errno: -111,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '172.20.0.10',
port: 443
},
[Symbol(kMessage)]: 'connect ECONNREFUSED 172.20.0.10:443'
}
}
POST /api/login 500 in 9ms
Error: connect ECONNREFUSED 172.20.0.10:443
at file:///app/node_modules/@neondatabase/serverless/index.mjs:1345:74
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async NeonPreparedQuery.execute (file:///app/node_modules/drizzle-orm/neon-serverless/session.js:76:20)
at async DatabaseStorage.getUserByUsername (file:///app/dist/index.js:893:20)
at async Strategy._verify (file:///app/dist/index.js:2461:24)
Server error: {
status: 500,
message: 'connect ECONNREFUSED 172.20.0.10:443',
error: ErrorEvent {
[Symbol(kTarget)]: WebSocket {
_events: [Object: null prototype],
_eventsCount: 4,
_maxListeners: undefined,
_binaryType: 'arraybuffer',
_closeCode: 1006,
_closeFrameReceived: false,
_closeFrameSent: false,
_closeMessage: <Buffer >,
_closeTimer: null,
_errorEmitted: true,
_extensions: {},
_paused: false,
_protocol: '',
_readyState: 3,
_receiver: null,
_sender: null,
_socket: null,
_bufferedAmount: 0,
_isServer: false,
_redirects: 0,
_autoPong: true,
_url: 'wss://logiflow-db/v2',
_req: null,
[Symbol(shapeMode)]: false,
[Symbol(kCapture)]: false
},
[Symbol(kType)]: 'error',
[Symbol(kError)]: Error: connect ECONNREFUSED 172.20.0.10:443
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1611:16) {
errno: -111,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '172.20.0.10',
port: 443
},
[Symbol(kMessage)]: 'connect ECONNREFUSED 172.20.0.10:443'
}
}
POST /api/login 500 in 23ms
Error: connect ECONNREFUSED 172.20.0.10:443
at file:///app/node_modules/@neondatabase/serverless/index.mjs:1345:74
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async NeonPreparedQuery.execute (file:///app/node_modules/drizzle-orm/neon-serverless/session.js:76:20)
at async DatabaseStorage.getUserByUsername (file:///app/dist/index.js:893:20)
at async Strategy._verify (file:///app/dist/index.js:2461:24)
HEAD /api/health 200 in 1ms
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

+39
View File
@@ -0,0 +1,39 @@
import { Pool } from 'pg';
import { drizzle } from 'drizzle-orm/node-postgres';
import * as schema from "@shared/schema";
console.log('🐳 PRODUCTION: Configuring standard PostgreSQL database');
if (!process.env.DATABASE_URL) {
throw new Error("DATABASE_URL must be set for production");
}
// Log connection details (without password)
const dbUrl = new URL(process.env.DATABASE_URL);
console.log('🐳 Database connection:', {
host: dbUrl.hostname,
port: dbUrl.port,
database: dbUrl.pathname.slice(1),
user: dbUrl.username
});
export const pool = new Pool({
connectionString: process.env.DATABASE_URL,
ssl: false, // No SSL for local Docker
max: 20,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 10000,
});
export const db = drizzle({ client: pool, schema });
// Test connection
pool.on('connect', () => {
console.log('✅ PostgreSQL connection established');
});
pool.on('error', (err) => {
console.error('❌ PostgreSQL connection error:', err);
});
console.log('✅ Production PostgreSQL database configured');
+57 -10
View File
@@ -1,15 +1,62 @@
import { Pool, neonConfig } from '@neondatabase/serverless';
import { drizzle } from 'drizzle-orm/neon-serverless';
import ws from "ws";
import * as schema from "@shared/schema";
neonConfig.webSocketConstructor = ws;
// Simple environment detection
const isProduction = process.env.NODE_ENV === 'production';
const dbUrl = process.env.DATABASE_URL;
if (!process.env.DATABASE_URL) {
throw new Error(
"DATABASE_URL must be set. Did you forget to provision a database?",
);
console.log('🔗 Database initialization:', {
NODE_ENV: process.env.NODE_ENV,
isProduction,
hasDbUrl: !!dbUrl,
dbHost: dbUrl ? new URL(dbUrl).hostname : 'none'
});
let db: any;
let pool: any;
if (isProduction && dbUrl && (dbUrl.includes('logiflow-db') || dbUrl.includes('localhost') || dbUrl.includes('127.0.0.1'))) {
// Standard PostgreSQL for production Docker
console.log('🐳 PRODUCTION: Using standard PostgreSQL');
const { Pool } = await import('pg');
const { drizzle } = await import('drizzle-orm/node-postgres');
pool = new Pool({
connectionString: dbUrl,
ssl: false,
max: 10,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 5000,
});
db = drizzle({ client: pool, schema });
// Test connection
try {
await pool.connect().then(client => {
console.log('✅ PostgreSQL connection test successful');
client.release();
});
} catch (error) {
console.error('❌ PostgreSQL connection test failed:', error);
}
} else {
// Fallback: use Neon for development (but will be overridden by MemStorage)
console.log('🔧 DEV: Using Neon (fallback, will use MemStorage)');
const { Pool, neonConfig } = await import('@neondatabase/serverless');
const { drizzle } = await import('drizzle-orm/neon-serverless');
const ws = await import('ws');
neonConfig.webSocketConstructor = ws.default;
if (dbUrl) {
pool = new Pool({ connectionString: dbUrl });
db = drizzle({ client: pool, schema });
} else {
// Create dummy instances for development
pool = null;
db = null;
console.log('🔧 DEV: No DATABASE_URL, using MemStorage');
}
}
export const pool = new Pool({ connectionString: process.env.DATABASE_URL });
export const db = drizzle({ client: pool, schema });
export { db, pool };
+4 -2
View File
@@ -1,10 +1,12 @@
import express, { type Request, Response, NextFunction } from "express";
import { createServer, type Server } from "http";
import { storage } from "./storage.js";
import { setupLocalAuth, requireAuth } from "./localAuth.production.js";
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
// Database will be configured in storage.js
import { storage } from "./storage.js";
import { setupLocalAuth, requireAuth } from "./localAuth.production.js";
// Get directory paths
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
+6 -3
View File
@@ -1963,6 +1963,9 @@ class MemStorage implements IStorage {
}
// Use MemStorage in development, DatabaseStorage in production
const isProduction = process.env.NODE_ENV === 'production' && process.env.DATABASE_URL;
export const storage = isProduction ? new DatabaseStorage() : new MemStorage();
console.log(isProduction ? '🐳 PRODUCTION: Using PostgreSQL storage' : '🔧 DEV: Using in-memory storage');
const isProduction = process.env.NODE_ENV === 'production';
const dbUrl = process.env.DATABASE_URL;
const isProductionDocker = isProduction && dbUrl && (dbUrl.includes('logiflow-db') || dbUrl.includes('localhost'));
export const storage = isProductionDocker ? new DatabaseStorage() : new MemStorage();
console.log(isProductionDocker ? '🐳 PRODUCTION: Using PostgreSQL storage' : '🔧 DEV: Using in-memory storage');