From d43f3762a304b3d88f340b59a64786fd89748ede Mon Sep 17 00:00:00 2001 From: bagasbanuna Date: Thu, 12 Feb 2026 16:29:03 +0800 Subject: [PATCH] Fixed Bug Server ## Summary This branch contains several bug fixes and performance improvements, primarily focusing on: - Database connection management - MQTT client stability - Logging optimization - API enhancements ## Detailed Changes ### Fixed Issues 1. **Database Connection Management** - Removed from user-validate API route to prevent connection pool exhaustion - Added proper connection handling in global Prisma setup - Reduced logging verbosity in production environments 2. **MQTT Client Improvements** - Enhanced MQTT client initialization with proper error handling - Added reconnection logic with configurable intervals - Implemented cleanup functions to prevent memory leaks - Added separate initialization logic for server and client-side code 3. **Logging Optimization** - Removed excessive logging in middleware that was causing high CPU usage - Configured appropriate log levels for development and production 4. **Component Stability** - Added safety checks in text editor component to prevent MQTT operations on the server side - Improved MQTT publishing logic with client availability checks ### New Files - - Utility functions for safe database operations ### Modified Files 1. - Removed problematic call 2. - Configured different logging levels for dev/prod - Removed process listeners that were causing disconnections - Exported prisma instance separately 3. - Removed excessive logging statements 4. - Enhanced initialization with error handling - Added reconnection and timeout configurations 5. - Added proper cleanup functions - Improved connection handling 6. - Added MQTT client availability checks - Prevented server-side MQTT operations ### Performance Improvements - Reduced database connection overhead - Optimized MQTT connection handling - Eliminated unnecessary logging in production - Better memory management with proper cleanup functions ### No Issue --- CHANGELOG_BRANCH.md | 63 +++++++++++++++++++ src/app/api/user-validate/route.ts | 4 +- .../new/comp_V3_text_editor_stiker.tsx | 11 ++-- src/lib/prisma.ts | 24 +++---- src/lib/prismaUtils.ts | 24 +++++++ src/middleware.tsx | 7 ++- src/util/mqtt_client.ts | 63 ++++++++++++++++++- src/util/mqtt_loader.tsx | 31 +++++---- 8 files changed, 188 insertions(+), 39 deletions(-) create mode 100644 CHANGELOG_BRANCH.md create mode 100644 src/lib/prismaUtils.ts diff --git a/CHANGELOG_BRANCH.md b/CHANGELOG_BRANCH.md new file mode 100644 index 00000000..8178d6db --- /dev/null +++ b/CHANGELOG_BRANCH.md @@ -0,0 +1,63 @@ +# Changelog for Branch: fixed-bug/12-feb-26 + +## Summary +This branch contains several bug fixes and performance improvements, primarily focusing on: +- Database connection management +- MQTT client stability +- Logging optimization +- API enhancements + +## Detailed Changes + +### Fixed Issues +1. **Database Connection Management** + - Removed `prisma.$disconnect()` from user-validate API route to prevent connection pool exhaustion + - Added proper connection handling in global Prisma setup + - Reduced logging verbosity in production environments + +2. **MQTT Client Improvements** + - Enhanced MQTT client initialization with proper error handling + - Added reconnection logic with configurable intervals + - Implemented cleanup functions to prevent memory leaks + - Added separate initialization logic for server and client-side code + +3. **Logging Optimization** + - Removed excessive logging in middleware that was causing high CPU usage + - Configured appropriate log levels for development and production + +4. **Component Stability** + - Added safety checks in text editor component to prevent MQTT operations on the server side + - Improved MQTT publishing logic with client availability checks + +### New Files +- `src/lib/prismaUtils.ts` - Utility functions for safe database operations + +### Modified Files +1. `src/app/api/user-validate/route.ts` + - Removed problematic `prisma.$disconnect()` call + +2. `src/lib/prisma.ts` + - Configured different logging levels for dev/prod + - Removed process listeners that were causing disconnections + - Exported prisma instance separately + +3. `src/middleware.tsx` + - Removed excessive logging statements + +4. `src/util/mqtt_client.ts` + - Enhanced initialization with error handling + - Added reconnection and timeout configurations + +5. `src/util/mqtt_loader.tsx` + - Added proper cleanup functions + - Improved connection handling + +6. `src/app_modules/_global/component/new/comp_V3_text_editor_stiker.tsx` + - Added MQTT client availability checks + - Prevented server-side MQTT operations + +### Performance Improvements +- Reduced database connection overhead +- Optimized MQTT connection handling +- Eliminated unnecessary logging in production +- Better memory management with proper cleanup functions \ No newline at end of file diff --git a/src/app/api/user-validate/route.ts b/src/app/api/user-validate/route.ts index a9c8fcb7..03dac63c 100644 --- a/src/app/api/user-validate/route.ts +++ b/src/app/api/user-validate/route.ts @@ -84,7 +84,7 @@ export async function GET(req: Request) { }, { status: 500 } ); - } finally { - await prisma.$disconnect(); } + // Removed prisma.$disconnect() from here to prevent connection pool exhaustion + // Prisma connections are handled globally and shouldn't be disconnected on each request } diff --git a/src/app_modules/_global/component/new/comp_V3_text_editor_stiker.tsx b/src/app_modules/_global/component/new/comp_V3_text_editor_stiker.tsx index e0affdfc..755e5d48 100644 --- a/src/app_modules/_global/component/new/comp_V3_text_editor_stiker.tsx +++ b/src/app_modules/_global/component/new/comp_V3_text_editor_stiker.tsx @@ -28,6 +28,7 @@ import { useRouter } from "next/navigation"; import { IconMoodSmileFilled } from "@tabler/icons-react"; import { listStiker } from "../../lib/stiker"; import { UIGlobal_Modal } from "../../ui"; +import mqtt_client from "@/util/mqtt_client"; const ReactQuill = dynamic( async () => { @@ -248,10 +249,12 @@ function ButtonAction({ value, lengthData }: ButtonActionProps) { ComponentGlobal_NotifikasiBerhasil(create.message); router.back(); - mqtt_client.publish( - "Forum_create_new", - JSON.stringify({ isNewPost: true, count: 1 }) - ); + if (typeof window !== 'undefined' && mqtt_client) { + mqtt_client.publish( + "Forum_create_new", + JSON.stringify({ isNewPost: true, count: 1 }) + ); + } } else { ComponentGlobal_NotifikasiGagal(create.message); } diff --git a/src/lib/prisma.ts b/src/lib/prisma.ts index 1620968d..bf87ef84 100644 --- a/src/lib/prisma.ts +++ b/src/lib/prisma.ts @@ -9,30 +9,21 @@ declare global { let prisma: PrismaClient; if (process.env.NODE_ENV === "production") { - prisma = new PrismaClient(); + prisma = new PrismaClient({ + // Reduce logging in production to improve performance + log: ['error', 'warn'], + }); } else { if (!global.prisma) { - global.prisma = new PrismaClient(); + global.prisma = new PrismaClient({ + log: ['error', 'warn', 'info', 'query'], // More verbose logging in development + }); } prisma = global.prisma; } // Tambahkan listener hanya jika belum ditambahkan sebelumnya if (!global.prismaListenersAdded) { - // Handle uncaught errors - process.on("uncaughtException", async (error) => { - console.error("Uncaught Exception:", error); - await prisma.$disconnect(); - process.exit(1); - }); - - // Handle unhandled promise rejections - process.on("unhandledRejection", async (error) => { - console.error("Unhandled Rejection:", error); - await prisma.$disconnect(); - process.exit(1); - }); - // Handle graceful shutdown process.on("SIGINT", async () => { console.log("Received SIGINT signal. Closing database connections..."); @@ -51,3 +42,4 @@ if (!global.prismaListenersAdded) { } export default prisma; +export { prisma }; diff --git a/src/lib/prismaUtils.ts b/src/lib/prismaUtils.ts new file mode 100644 index 00000000..b2c473db --- /dev/null +++ b/src/lib/prismaUtils.ts @@ -0,0 +1,24 @@ +import { prisma } from './prisma'; + +/** + * Utility function to safely execute Prisma operations + * This prevents improper disconnection of the Prisma client + * which was causing high CPU usage and connection pool issues + */ +export async function executeDbOperation( + operation: () => Promise, + errorMessage: string = "Database operation failed" +): Promise<{ success: boolean; data?: T; error?: string }> { + try { + const data = await operation(); + return { success: true, data }; + } catch (error) { + console.error(errorMessage, error); + return { success: false, error: (error as Error).message }; + } + // Note: We intentionally do NOT call prisma.$disconnect() here + // Prisma manages connection pooling automatically and disconnecting + // on each request causes performance issues +} + +export { prisma }; \ No newline at end of file diff --git a/src/middleware.tsx b/src/middleware.tsx index 5c421996..89f659f3 100644 --- a/src/middleware.tsx +++ b/src/middleware.tsx @@ -66,9 +66,10 @@ export const middleware = async (req: NextRequest) => { const { pathname } = req.nextUrl; const apiBaseUrl = new URL(req.url).origin || process.env.NEXT_PUBLIC_API_URL; - const dbUrl = process.env.DATABASE_URL; - console.log("DATABASE_URL >>", dbUrl); - console.log("URL Access >>", req.url); + // Removed excessive logging that was causing high CPU usage + // const dbUrl = process.env.DATABASE_URL; + // console.log("DATABASE_URL >>", dbUrl); + // console.log("URL Access >>", req.url); // Handle CORS preflight const corsResponse = handleCors(req); diff --git a/src/util/mqtt_client.ts b/src/util/mqtt_client.ts index 5164f0da..d7b861b4 100644 --- a/src/util/mqtt_client.ts +++ b/src/util/mqtt_client.ts @@ -4,7 +4,66 @@ declare global { var mqtt_client: mqtt.MqttClient; } -const mqtt_client = - globalThis.mqtt_client || mqtt.connect("wss://io.wibudev.com"); +// Initialize MQTT client with proper error handling and reconnection settings +let mqtt_client: mqtt.MqttClient; + +if (typeof window === 'undefined') { + // Server-side code + mqtt_client = globalThis.mqtt_client || (() => { + const client = mqtt.connect("wss://io.wibudev.com", { + reconnectPeriod: 5000, // Reconnect every 5 seconds + connectTimeout: 30 * 1000, // 30 second timeout + // Clean session to avoid message queue buildup + clean: true, + // Reduce unnecessary pings + keepalive: 60 + }); + + // Prevent multiple initializations + globalThis.mqtt_client = client; + + // Add error handling + client.on('error', (error) => { + console.error('MQTT Connection Error:', error); + }); + + client.on('reconnect', () => { + console.log('MQTT Reconnecting...'); + }); + + client.on('close', () => { + console.log('MQTT Connection Closed'); + }); + + return client; + })(); +} else { + // Client-side code - initialize only once + if (!(globalThis as any).mqtt_client) { + (globalThis as any).mqtt_client = mqtt.connect("wss://io.wibudev.com", { + reconnectPeriod: 5000, // Reconnect every 5 seconds + connectTimeout: 30 * 1000, // 30 second timeout + // Clean session to avoid message queue buildup + clean: true, + // Reduce unnecessary pings + keepalive: 60 + }); + + // Add error handling + (globalThis as any).mqtt_client.on('error', (error: any) => { + console.error('MQTT Connection Error:', error); + }); + + (globalThis as any).mqtt_client.on('reconnect', () => { + console.log('MQTT Reconnecting...'); + }); + + (globalThis as any).mqtt_client.on('close', () => { + console.log('MQTT Connection Closed'); + }); + } + + mqtt_client = (globalThis as any).mqtt_client; +} export default mqtt_client; diff --git a/src/util/mqtt_loader.tsx b/src/util/mqtt_loader.tsx index eb47c73b..17a6ae9d 100644 --- a/src/util/mqtt_loader.tsx +++ b/src/util/mqtt_loader.tsx @@ -3,20 +3,27 @@ import { useEffect } from "react"; import mqtt_client from "./mqtt_client"; -export default function MqttLoader() { +export default function MqttLoader() { useEffect(() => { - mqtt_client.on("connect", () => { - console.log("connected"); - }); + // Only set up connection handlers once + const handleConnect = () => { + console.log("MQTT connected"); + }; + + const handleError = (error: any) => { + console.error("MQTT Error:", error); + }; + + // Subscribe to events + mqtt_client.on("connect", handleConnect); + mqtt_client.on("error", handleError); + + // Cleanup function to unsubscribe when component unmounts + return () => { + mqtt_client.off("connect", handleConnect); + mqtt_client.off("error", handleError); + }; }, []); return null; - - // <> - // - // - // - // - // - // ); }