mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-29 23:12:38 +08:00
* 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
94 lines
2.4 KiB
TypeScript
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()
|