diff --git a/config/mariadb.ini.template b/config/mariadb.ini.template index fa7828e..bbc0373 100644 --- a/config/mariadb.ini.template +++ b/config/mariadb.ini.template @@ -7,7 +7,16 @@ character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci log-error="{{LOG_FILE}}" +# Performance Optimizations +max_allowed_packet=1G +innodb_buffer_pool_size=512M +innodb_log_file_size=128M +innodb_flush_log_at_trx_commit=2 +innodb_doublewrite=0 +innodb_lock_wait_timeout=600 + [client] port={{PORT}} socket="{{SOCKET}}" default-character-set=utf8mb4 +max_allowed_packet=1G diff --git a/logo/icon.ico b/logo/icon.ico index 4cfd30f..2e7deab 100644 Binary files a/logo/icon.ico and b/logo/icon.ico differ diff --git a/package.json b/package.json index a71018c..ce4055c 100644 --- a/package.json +++ b/package.json @@ -56,5 +56,21 @@ "prettier": "^3.3.2", "typescript": "^5.5.2", "vite": "^5.3.1" + }, + "build": { + "appId": "com.multiphp", + "productName": "Multi-PHP", + "directories": { + "output": "dist" + }, + "win": { + "icon": "resources/icon.ico" + }, + "mac": { + "icon": "resources/icon.png" + }, + "linux": { + "icon": "resources/icon.png" + } } -} +} \ No newline at end of file diff --git a/resources/icon.ico b/resources/icon.ico new file mode 100644 index 0000000..2e7deab Binary files /dev/null and b/resources/icon.ico differ diff --git a/resources/icon.png b/resources/icon.png new file mode 100644 index 0000000..1c6651e Binary files /dev/null and b/resources/icon.png differ diff --git a/resources/icon.svg b/resources/icon.svg new file mode 100644 index 0000000..581c23c --- /dev/null +++ b/resources/icon.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/main/index.ts b/src/main/index.ts index 429da10..0805685 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -8,8 +8,10 @@ let tray: Tray | null = null let mainWindow: BrowserWindow | null = null function createTray(): void { - // Use a simple colored pixel if no icon is available for now - const icon = nativeImage.createFromPath(join(__dirname, '../../resources/icon.png')) + const iconPath = process.platform === 'win32' + ? join(__dirname, '../../resources/icon.ico') + : join(__dirname, '../../resources/icon.png') + const icon = nativeImage.createFromPath(iconPath) tray = new Tray(icon.isEmpty() ? nativeImage.createEmpty() : icon) const contextMenu = Menu.buildFromTemplate([ @@ -17,7 +19,7 @@ function createTray(): void { { type: 'separator' }, { label: 'Göster/Gizle', click: () => { - if (mainWindow) { + if (mainWindow && !mainWindow.isDestroyed()) { if (mainWindow.isVisible()) mainWindow.hide() else mainWindow.show() } @@ -38,7 +40,7 @@ function createTray(): void { tray.setContextMenu(contextMenu) tray.on('double-click', () => { - if (mainWindow) mainWindow.show() + if (mainWindow && !mainWindow.isDestroyed()) mainWindow.show() }) } @@ -48,6 +50,7 @@ function createWindow(): void { height: 800, show: false, autoHideMenuBar: true, + icon: join(__dirname, '../../resources/icon.png'), webPreferences: { preload: join(__dirname, '../preload/index.js'), sandbox: false @@ -55,7 +58,11 @@ function createWindow(): void { }) mainWindow.on('ready-to-show', () => { - if (mainWindow) mainWindow.show() + if (mainWindow && !mainWindow.isDestroyed()) mainWindow.show() + }) + + mainWindow.on('closed', () => { + mainWindow = null }) mainWindow.webContents.setWindowOpenHandler((details) => { diff --git a/src/main/services/MariaDbOperationService.ts b/src/main/services/MariaDbOperationService.ts index 07bca5d..97d5e3e 100644 --- a/src/main/services/MariaDbOperationService.ts +++ b/src/main/services/MariaDbOperationService.ts @@ -143,10 +143,48 @@ export class MariaDbOperationService { // 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.pipe(child.stdin) + + 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.`) + } else { + throw e + } + } + } + }) + + 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}`) + } + }) child.stdout.on('data', (data) => onProgress?.(data.toString())) child.stderr.on('data', (data) => onProgress?.(data.toString())) @@ -199,6 +237,9 @@ export class MariaDbOperationService { `--host=${config.host}`, `--port=${config.port}`, `--user=${config.rootUser}`, + '--quick', + '--single-transaction', + '--max_allowed_packet=1G', dbName, '--routines', '--triggers'