feat: implement IPC handlers for service management and add ProcessManager for background process control

This commit is contained in:
Ümit Tunç
2026-03-30 07:00:59 +03:00
parent bf99a4fb49
commit 862364d4d8
2 changed files with 64 additions and 2 deletions
+5 -2
View File
@@ -168,10 +168,14 @@ export function registerIpcHandlers(): void {
if (!binPath) return { success: false, message: 'MySQL executable bulunamadı. Lütfen indirin.' }
const mysqlPort = mysqlId ? (settings.mysqlPorts?.[mysqlId] || '3306') : settings.mysqlPort
// Force kill this specific version if running or generic mysql
// Actually processManager handles by serviceName
await processManager.forceKillAll(serviceName)
// Also kill anything else listening on the same port
await processManager.killByPort(serviceName, mysqlPort)
// Initialize if data directory is empty
if (!fs.existsSync(dataDir) || fs.readdirSync(dataDir).length === 0) {
if (!fs.existsSync(dataDir)) fs.mkdirSync(dataDir, { recursive: true })
@@ -194,7 +198,6 @@ export function registerIpcHandlers(): void {
}
}
const mysqlPort = mysqlId ? (settings.mysqlPorts?.[mysqlId] || '3306') : settings.mysqlPort
const sanitizedServiceName = serviceName.replace(/:/g, '_')
const logFile = path.join(configService.getBasePath(), 'logs', `${sanitizedServiceName}_error.log`)
+59
View File
@@ -222,6 +222,65 @@ export class ProcessManager {
})
}
async killByPort(name: string, port: string | number): Promise<boolean> {
return new Promise((resolve) => {
if (!port) return resolve(true)
this.addLog(name, `Checking if port ${port} is in use...`)
// findstr will return lines containing the port and "LISTENING"
const cmd = `netstat -ano | findstr :${port} | findstr LISTENING`
const netstat = spawn('cmd.exe', ['/c', cmd], { windowsHide: true, shell: false })
let output = ''
netstat.stdout?.on('data', (data) => {
output += data.toString()
})
netstat.on('close', () => {
const lines = output.split('\n').filter(l => l.trim())
if (lines.length === 0) {
this.addLog(name, `Port ${port} is free.`)
return resolve(true)
}
// netstat output format: TCP 0.0.0.0:3306 0.0.0.0:0 LISTENING 1234
// We want the last part, which is the PID
const pids = new Set<string>()
lines.forEach(line => {
const parts = line.trim().split(/\s+/)
const pid = parts[parts.length - 1]
if (pid && !isNaN(parseInt(pid)) && parseInt(pid) > 0) {
pids.add(pid)
}
})
if (pids.size === 0) {
this.addLog(name, `Port ${port} in use but PID not found.`)
return resolve(true)
}
this.addLog(name, `Port ${port} is used by PIDs: ${Array.from(pids).join(', ')}. Terminating...`)
const killProcesses = Array.from(pids).map(pid => {
return new Promise<void>((res) => {
const tk = spawn('taskkill', ['/F', '/PID', pid, '/T'], { windowsHide: true, shell: false })
tk.on('close', () => res())
})
})
Promise.all(killProcesses).then(() => {
this.addLog(name, `Successfully cleared port ${port}.`)
resolve(true)
})
})
netstat.on('error', (err) => {
this.addLog(name, `Port check error: ${err.message}`)
resolve(true)
})
})
}
isServiceRunning(name: string): boolean {
return this.processes.has(name)
}