cherry-studio/src/main/apiServer/server.ts
Pleasure1234 b4810bb487
fix: improve api-server startup and error handling logic (#10794)
* fix: improve server startup and error handling logic

Refactored ApiServer to clean up failed server instances and ensure proper handling of server state. Updated loggerService import to use shared logger and improved error handling during server startup.

* Update server.ts
2025-10-18 14:15:08 +08:00

94 lines
2.4 KiB
TypeScript

import { createServer } from 'node:http'
import { loggerService } from '@logger'
import { agentService } from '../services/agents'
import { app } from './app'
import { config } from './config'
const logger = loggerService.withContext('ApiServer')
const GLOBAL_REQUEST_TIMEOUT_MS = 5 * 60_000
const GLOBAL_HEADERS_TIMEOUT_MS = GLOBAL_REQUEST_TIMEOUT_MS + 5_000
const GLOBAL_KEEPALIVE_TIMEOUT_MS = 60_000
export class ApiServer {
private server: ReturnType<typeof createServer> | null = null
async start(): Promise<void> {
if (this.server && this.server.listening) {
logger.warn('Server already running')
return
}
// Clean up any failed server instance
if (this.server && !this.server.listening) {
logger.warn('Cleaning up failed server instance')
this.server = null
}
// Load config
const { port, host } = await config.load()
// Initialize AgentService
logger.info('Initializing AgentService')
await agentService.initialize()
logger.info('AgentService initialized')
// Create server with Express app
this.server = createServer(app)
this.applyServerTimeouts(this.server)
// Start server
return new Promise((resolve, reject) => {
this.server!.listen(port, host, () => {
logger.info('API server started', { host, port })
resolve()
})
this.server!.on('error', (error) => {
// Clean up the server instance if listen fails
this.server = null
reject(error)
})
})
}
private applyServerTimeouts(server: ReturnType<typeof createServer>): void {
server.requestTimeout = GLOBAL_REQUEST_TIMEOUT_MS
server.headersTimeout = Math.max(GLOBAL_HEADERS_TIMEOUT_MS, server.requestTimeout + 1_000)
server.keepAliveTimeout = GLOBAL_KEEPALIVE_TIMEOUT_MS
server.setTimeout(0)
}
async stop(): Promise<void> {
if (!this.server) return
return new Promise((resolve) => {
this.server!.close(() => {
logger.info('API server stopped')
this.server = null
resolve()
})
})
}
async restart(): Promise<void> {
await this.stop()
await config.reload()
await this.start()
}
isRunning(): boolean {
const hasServer = this.server !== null
const isListening = this.server?.listening || false
const result = hasServer && isListening
logger.debug('isRunning check', { hasServer, isListening, result })
return result
}
}
export const apiServer = new ApiServer()