From 443f5641aa40e66d2394869a529bf21b10949247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Cmit=20Tun=C3=A7?= Date: Mon, 30 Mar 2026 13:42:57 +0300 Subject: [PATCH] feat: implement MariaDbOperationService and add optimized MariaDB configuration template --- config/mariadb.ini.template | 8 ++- src/main/services/MariaDbOperationService.ts | 72 ++++++++++---------- 2 files changed, 41 insertions(+), 39 deletions(-) diff --git a/config/mariadb.ini.template b/config/mariadb.ini.template index bbc0373..42d595e 100644 --- a/config/mariadb.ini.template +++ b/config/mariadb.ini.template @@ -7,13 +7,15 @@ character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci log-error="{{LOG_FILE}}" -# Performance Optimizations +# Performance & Scale Optimizations max_allowed_packet=1G -innodb_buffer_pool_size=512M -innodb_log_file_size=128M +innodb_buffer_pool_size=1G +innodb_log_file_size=256M innodb_flush_log_at_trx_commit=2 innodb_doublewrite=0 innodb_lock_wait_timeout=600 +innodb_strict_mode=0 +innodb_default_row_format=DYNAMIC [client] port={{PORT}} diff --git a/src/main/services/MariaDbOperationService.ts b/src/main/services/MariaDbOperationService.ts index 97d5e3e..38eb113 100644 --- a/src/main/services/MariaDbOperationService.ts +++ b/src/main/services/MariaDbOperationService.ts @@ -3,6 +3,7 @@ import path from 'path' import { spawn } from 'child_process' import decompress from 'decompress' import zlib from 'zlib' +import { pipeline, PassThrough } from 'stream' export interface MariaDbConfig { binPath: string @@ -130,7 +131,8 @@ export class MariaDbOperationService { `--host=${config.host}`, `--port=${config.port}`, `--user=${config.rootUser}`, - `--database=${dbName}` + `--database=${dbName}`, + '--max_allowed_packet=1G' ] if (config.rootPass) { @@ -139,50 +141,48 @@ export class MariaDbOperationService { onProgress?.(`Executing: "${mariaDbPath}" ${args.join(' ')} < "${sqlFilePath}"`) - const child = spawn(mariaDbPath, args, { windowsHide: true }) + const child = spawn(mariaDbPath, args, { windowsHide: true, stdio: ['pipe', 'pipe', 'pipe'] }) + + // Create a wrapper stream to prepend/append SQL commands + const combinedStream = new PassThrough() + + // Send optimization headers + combinedStream.write('SET GLOBAL innodb_strict_mode = 0;\n') + combinedStream.write('SET SESSION innodb_strict_mode = 0;\n') + combinedStream.write('SET foreign_key_checks = 0;\n') + combinedStream.write('SET unique_checks = 0;\n') + combinedStream.write('SET autocommit = 0;\n') + combinedStream.write('SET sql_log_bin = 0;\n') - // Pipe the file content to stdin const fileStream = fs.createReadStream(sqlFilePath) - // Performance optimizations - child.stdin.write('SET foreign_key_checks = 0;\n') - child.stdin.write('SET unique_checks = 0;\n') - child.stdin.write('SET autocommit = 0;\n') - child.stdin.write('SET sql_log_bin = 0;\n') - - fileStream.on('error', (err) => { - onProgress?.(`File read error: ${err.message}`) - }) - - fileStream.on('data', (chunk) => { - if (child.stdin.writable) { - try { - child.stdin.write(chunk) - } catch (e: any) { - if (e.code === 'EPIPE') { - onProgress?.(`Warning: EPIPE error encountered. The child process may have closed the pipe early.`) + // Use pipeline for robust error handling and backpressure + pipeline( + fileStream, + combinedStream, + child.stdin, + (err) => { + if (err) { + if (err.code === 'EPIPE' || err.code === 'ECONNRESET') { + onProgress?.(`Notice: Pipe closed early (${err.code}). This is often normal if MariaDB finished early.`) + } else if (err.code === 'ENOBUFS') { + onProgress?.(`Error: System buffer overflow (ENOBUFS). The file might be too large for current system limits.`) } else { - throw e + onProgress?.(`Stream error: ${err.message}`) } } } - }) + ) + // When file ends, send footer fileStream.on('end', () => { - if (child.stdin.writable) { - child.stdin.write('\nCOMMIT;\n') - child.stdin.write('SET foreign_key_checks = 1;\n') - child.stdin.write('SET unique_checks = 1;\n') - child.stdin.write('SET autocommit = 1;\n') - child.stdin.end() - } - }) - - child.stdin.on('error', (err: any) => { - if (err.code === 'EPIPE') { - onProgress?.(`Notice: Broken pipe (EPIPE). This usually means MariaDB finished or aborted before we finished writing.`) - } else { - onProgress?.(`Stdin error: ${err.message}`) + // Ensure we don't write to a closed stream + if (!combinedStream.writableEnded) { + combinedStream.write('\nCOMMIT;\n') + combinedStream.write('SET foreign_key_checks = 1;\n') + combinedStream.write('SET unique_checks = 1;\n') + combinedStream.write('SET autocommit = 1;\n') + combinedStream.end() } })