Skip to content

Commit 7215512

Browse files
xiaoY233bennylii
andcommitted
Reduce log I/O and fix session cleanup
Co-authored-by: bennylii <13807507+bennylii@users.noreply.github.com>
1 parent fea5f12 commit 7215512

9 files changed

Lines changed: 193 additions & 67 deletions

File tree

src/main/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { createWindow, getMainWindow, loadUrl, loadFile, openDevTools } from './
44
import { createTrayManager, TrayManager } from './tray/TrayManager'
55
import { registerIpcHandlers } from './ipc/handlers'
66
import { UpdaterManager } from './updater'
7+
import { storeManager } from './store/store'
78

89
// Prevent uncaught exceptions from crashing the app
910
process.on('uncaughtException', (error) => {
@@ -125,6 +126,7 @@ async function loadAppContent(mainWindow: BrowserWindow): Promise<void> {
125126

126127
function cleanup(): void {
127128
console.log('Application is exiting, performing cleanup...')
129+
storeManager.flushPendingWrites()
128130
const updaterManager = UpdaterManager.getInstance()
129131
updaterManager.destroy()
130132
}

src/main/proxy/forwarder.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,7 @@ CRITICAL RULES:
828828
const originalEnd = transformedStream.end.bind(transformedStream)
829829
transformedStream.end = function(chunk?: any, encoding?: any, callback?: any) {
830830
const realChatId = handler.getConversationId()
831-
if (realChatId && realChatId.startsWith('kimi-') === false) {
831+
if (realChatId) {
832832
adapter.deleteConversation(realChatId).catch(err => {
833833
console.error('[Kimi] Failed to delete conversation:', err)
834834
})
@@ -854,7 +854,7 @@ CRITICAL RULES:
854854

855855
if (shouldDeleteSession()) {
856856
const realChatId = handler.getConversationId()
857-
if (realChatId && realChatId.startsWith('kimi-') === false) {
857+
if (realChatId) {
858858
await adapter.deleteConversation(realChatId)
859859
}
860860
}
@@ -1006,22 +1006,22 @@ CRITICAL RULES:
10061006
}
10071007
}
10081008

1009-
const deleteChatCallback = shouldDeleteSession()
1010-
? async (cid: string) => {
1011-
try {
1012-
await adapter.deleteChat(cid)
1013-
} catch (err) {
1014-
console.error('[QwenAI] Failed to delete chat:', err)
1015-
}
1016-
}
1017-
: undefined
1018-
1019-
const handler = new QwenAiStreamHandler(actualModel, deleteChatCallback)
1009+
const handler = new QwenAiStreamHandler(actualModel)
10201010
handler.setChatId(chatId)
10211011

10221012
if (request.stream) {
10231013
const transformedStream = await handler.handleStream(response.data)
10241014

1015+
if (shouldDeleteSession()) {
1016+
const originalEnd = transformedStream.end.bind(transformedStream)
1017+
transformedStream.end = function(chunk?: any, encoding?: any, callback?: any) {
1018+
adapter.deleteChat(chatId).catch(err => {
1019+
console.error('[QwenAI] Failed to delete chat:', err)
1020+
})
1021+
return originalEnd(chunk, encoding, callback)
1022+
}
1023+
}
1024+
10251025
return {
10261026
success: true,
10271027
status: response.status,
@@ -1037,8 +1037,8 @@ CRITICAL RULES:
10371037

10381038
this.applyToolCallsToResponse(result, request.model, request.tools)
10391039

1040-
if (deleteChatCallback) {
1041-
await deleteChatCallback(chatId)
1040+
if (shouldDeleteSession()) {
1041+
await adapter.deleteChat(chatId)
10421042
}
10431043

10441044
return {

src/main/proxy/routes/chat.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ router.post('/completions', async (ctx: Context) => {
261261
todayUsed: (account.todayUsed || 0) + 1,
262262
})
263263

264-
storeManager.addLog('info', `Request succeeded`, {
264+
storeManager.addLog('debug', `Request succeeded`, {
265265
requestId,
266266
providerId: provider.id,
267267
accountId: account.id,

src/main/proxy/routes/completions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ router.post('/completions', async (ctx: Context) => {
170170
todayUsed: (account.todayUsed || 0) + 1,
171171
})
172172

173-
storeManager.addLog('info', `Request succeeded`, {
173+
storeManager.addLog('debug', `Request succeeded`, {
174174
requestId,
175175
providerId: provider.id,
176176
accountId: account.id,

src/main/proxy/server.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { proxyStatusManager } from './status'
1313
import { storeManager } from '../store/store'
1414
import { sessionManager } from './sessionManager'
1515

16+
const SLOW_REQUEST_THRESHOLD_MS = 1500
17+
1618
/**
1719
* Proxy Server Class
1820
*/
@@ -129,16 +131,19 @@ export class ProxyServer {
129131
await next()
130132

131133
const latency = Date.now() - startTime
132-
const logLevel = ctx.status >= 400 ? 'warn' : 'info'
134+
const shouldRecordAccessLog =
135+
!ctx.path.startsWith('/v1/models') &&
136+
(ctx.status >= 400 || latency >= SLOW_REQUEST_THRESHOLD_MS)
133137

134-
if (!ctx.path.startsWith('/v1/models')) {
135-
storeManager.addLog(logLevel, `${ctx.method} ${ctx.path} ${ctx.status} ${latency}ms`, {
138+
if (shouldRecordAccessLog) {
139+
storeManager.addLog('warn', `${ctx.method} ${ctx.path} ${ctx.status} ${latency}ms`, {
136140
data: {
137141
method: ctx.method,
138142
path: ctx.path,
139143
status: ctx.status,
140144
latency,
141145
clientIP: ctx.ip,
146+
slowRequest: latency >= SLOW_REQUEST_THRESHOLD_MS,
142147
},
143148
})
144149
}

src/main/requestLogs/manager.ts

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ export class RequestLogManager {
2626
private requestLogs: RequestLogEntry[] = []
2727
private config: RequestLogConfig
2828
private initialized = false
29+
private persistTimer: NodeJS.Timeout | null = null
30+
private dirty = false
31+
private readonly persistDelayMs = 2000
2932

3033
constructor(options: RequestLogManagerOptions) {
3134
this.storageDir = options.storageDir
@@ -44,7 +47,7 @@ export class RequestLogManager {
4447
setConfig(config: Partial<RequestLogConfig>): void {
4548
this.config = normalizeRequestLogConfig(config)
4649
this.requestLogs = trimRequestLogsToMaxEntries(this.requestLogs, this.config)
47-
this.persist()
50+
this.schedulePersist()
4851
}
4952

5053
async migrateLegacyLogs(legacyLogs: RequestLogEntry[]): Promise<boolean> {
@@ -63,7 +66,7 @@ export class RequestLogManager {
6366
})),
6467
this.config,
6568
)
66-
this.persist()
69+
this.schedulePersist()
6770

6871
return true
6972
}
@@ -82,7 +85,7 @@ export class RequestLogManager {
8285

8386
this.requestLogs.push(logEntry)
8487
this.requestLogs = trimRequestLogsToMaxEntries(this.requestLogs, this.config)
85-
this.persist()
88+
this.schedulePersist()
8689

8790
return logEntry
8891
}
@@ -102,7 +105,7 @@ export class RequestLogManager {
102105
...this.requestLogs[index],
103106
...sanitizeRequestLogUpdates(updates, this.config),
104107
}
105-
this.persist()
108+
this.schedulePersist()
106109
return true
107110
}
108111

@@ -135,7 +138,7 @@ export class RequestLogManager {
135138
clearRequestLogs(): void {
136139
this.ensureInitialized()
137140
this.requestLogs = []
138-
this.persist()
141+
this.schedulePersist()
139142
}
140143

141144
getRequestLogStats(): RequestLogStats {
@@ -188,6 +191,19 @@ export class RequestLogManager {
188191
return [...this.requestLogs]
189192
}
190193

194+
flushSync(): void {
195+
if (!this.initialized) {
196+
return
197+
}
198+
199+
if (this.persistTimer) {
200+
clearTimeout(this.persistTimer)
201+
this.persistTimer = null
202+
}
203+
204+
this.persistNow()
205+
}
206+
191207
private ensureInitialized(): void {
192208
if (!this.initialized) {
193209
throw new Error('RequestLogManager is not initialized')
@@ -217,9 +233,27 @@ export class RequestLogManager {
217233
.filter((entry): entry is RequestLogEntry => entry !== null)
218234
}
219235

220-
private persist(): void {
236+
private schedulePersist(): void {
237+
this.dirty = true
238+
239+
if (this.persistTimer) {
240+
clearTimeout(this.persistTimer)
241+
}
242+
243+
this.persistTimer = setTimeout(() => {
244+
this.persistTimer = null
245+
this.persistNow()
246+
}, this.persistDelayMs)
247+
}
248+
249+
private persistNow(): void {
250+
if (!this.dirty) {
251+
return
252+
}
253+
221254
const content = this.requestLogs.map((entry) => JSON.stringify(entry)).join('\n')
222255
writeFileSync(this.logFile, content, 'utf-8')
256+
this.dirty = false
223257
}
224258
}
225259

0 commit comments

Comments
 (0)