fix: configure postgres idle timeout and connection recycling for Railway

Railway proxy closes idle DB connections after ~60s, causing
CONNECTION_CLOSED errors on stale sockets. Set idle_timeout=20s and
max_lifetime=5m so postgres-js recycles connections before they die.

Also fix sendCommand to fall back to persistent device ID on reconnect.
This commit is contained in:
Sanju Sivalingam
2026-02-18 13:56:34 +05:30
parent 3bab84f611
commit 88af77ddc7
4 changed files with 13 additions and 3 deletions

View File

@@ -7,6 +7,7 @@ import com.thisux.droidclaw.model.DeviceInfoMsg
import com.thisux.droidclaw.model.ServerMessage import com.thisux.droidclaw.model.ServerMessage
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO import io.ktor.client.engine.cio.CIO
import io.ktor.client.engine.cio.endpoint
import io.ktor.client.plugins.websocket.WebSockets import io.ktor.client.plugins.websocket.WebSockets
import io.ktor.client.plugins.websocket.webSocket import io.ktor.client.plugins.websocket.webSocket
import io.ktor.websocket.Frame import io.ktor.websocket.Frame

View File

@@ -3,5 +3,9 @@ import postgres from "postgres";
import { env } from "./env.js"; import { env } from "./env.js";
import * as schema from "./schema.js"; import * as schema from "./schema.js";
const client = postgres(env.DATABASE_URL); const client = postgres(env.DATABASE_URL, {
idle_timeout: 20, // close idle connections after 20s (Railway proxy kills at ~60s)
max_lifetime: 60 * 5, // recycle connections every 5 minutes
connect_timeout: 10, // fail fast on connection issues
});
export const db = drizzle(client, { schema }); export const db = drizzle(client, { schema });

View File

@@ -122,7 +122,8 @@ class SessionManager {
command: Record<string, unknown>, command: Record<string, unknown>,
timeout = DEFAULT_COMMAND_TIMEOUT timeout = DEFAULT_COMMAND_TIMEOUT
): Promise<unknown> { ): Promise<unknown> {
const device = this.devices.get(deviceId); // Try ephemeral ID first, then fall back to persistent DB ID (handles reconnects)
const device = this.devices.get(deviceId) ?? this.getDeviceByPersistentId(deviceId);
if (!device) { if (!device) {
return Promise.reject(new Error(`Device ${deviceId} not connected`)); return Promise.reject(new Error(`Device ${deviceId} not connected`));
} }

View File

@@ -5,6 +5,10 @@ import { env } from '$env/dynamic/private';
if (!env.DATABASE_URL) throw new Error('DATABASE_URL is not set'); if (!env.DATABASE_URL) throw new Error('DATABASE_URL is not set');
const client = postgres(env.DATABASE_URL); const client = postgres(env.DATABASE_URL, {
idle_timeout: 20,
max_lifetime: 60 * 5,
connect_timeout: 10
});
export const db = drizzle(client, { schema }); export const db = drizzle(client, { schema });