refactor: split monolith into 3 microservices (frontend, backend, discord-gateway)
- Extract services into services/{frontend,backend,discord-gateway}
- Create packages/shared/ for shared logger, errors, utils, types
- Setup Modular MVC pattern in backend (controller→service→repository)
- Setup event-driven architecture in discord-gateway with Redis pub/sub
- Move Docker files to infra/docker/ with per-service Dockerfiles
- Update docker-compose.yml to use Traefik-only routing (no port exposes)
- Update GitHub Actions deploy workflow for multi-service matrix build
- Fix all import paths and resolve type errors across all services
- All 3 services pass tsc --noEmit clean
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
bda8304bb9
commit
c48a0c5e3b
@@ -0,0 +1,58 @@
|
||||
import { drizzle } from "drizzle-orm/node-postgres";
|
||||
import { Pool } from "pg";
|
||||
import { config } from "../config/index.js";
|
||||
import { createChildLogger } from "../logger/index.js";
|
||||
|
||||
const logger = createChildLogger("database");
|
||||
|
||||
let pool: Pool | null = null;
|
||||
let db: ReturnType<typeof drizzle> | null = null;
|
||||
|
||||
export async function initializeDatabase() {
|
||||
if (db) {
|
||||
logger.warn("Database already initialized");
|
||||
return db;
|
||||
}
|
||||
|
||||
const databaseUrl =
|
||||
config.DATABASE_URL ||
|
||||
`postgresql://${config.DATABASE_USER}${config.DATABASE_PASSWORD ? `:${config.DATABASE_PASSWORD}` : ""}@${config.DATABASE_HOST}:${config.DATABASE_PORT}/${config.DATABASE_NAME}`;
|
||||
|
||||
pool = new Pool({
|
||||
connectionString: databaseUrl,
|
||||
});
|
||||
|
||||
pool.on("error", (err) => {
|
||||
logger.error({ err }, "Unexpected error on idle client");
|
||||
});
|
||||
|
||||
try {
|
||||
const client = await pool.connect();
|
||||
client.release();
|
||||
logger.info("Database connection successful");
|
||||
} catch (err) {
|
||||
logger.error({ err }, "Failed to connect to database");
|
||||
throw err;
|
||||
}
|
||||
|
||||
db = drizzle(pool);
|
||||
return db;
|
||||
}
|
||||
|
||||
export function getDatabase() {
|
||||
if (!db) {
|
||||
throw new Error(
|
||||
"Database not initialized. Call initializeDatabase() first.",
|
||||
);
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
export async function closeDatabase() {
|
||||
if (pool) {
|
||||
await pool.end();
|
||||
pool = null;
|
||||
db = null;
|
||||
logger.info("Database connection closed");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user