mirror of
https://github.com/hellodigua/ChatLab.git
synced 2026-10-25 17:54:34 +08:00
fix(electron): close worker database before deleting sessions
This commit is contained in:
1 parent
b130e43e73
commit
1a774592ff
4 files changed
+22
-3
No files matched your search
@@ -44,6 +44,7 @@ import { assertDesktopDataDirCompatible, getDesktopAppVersion } from '../runtime
|
||||
import { resolveDesktopNativeBinding } from '../runtime/native-sqlite'
|
||||
import { resolveModelDownloadProxyUrl } from '../network/proxy'
|
||||
import { getDefaultUserDataDir, getDownloadsDir, getUserDataDir } from '../paths/locations'
|
||||
import { closeDatabase as closeWorkerDatabase } from '../worker/workerManager'
|
||||
import { configureInternalHttpServer } from './http'
|
||||
|
||||
export interface InternalEndpoint {
|
||||
@@ -148,6 +149,10 @@ export async function startInternalServer(
|
||||
dbManager: newDbManager,
|
||||
sessionAdapter,
|
||||
pathProvider,
|
||||
beforeDeleteSession: async (sessionId) => {
|
||||
// The Desktop worker caches readonly SQLite handles; Windows cannot unlink an open database file.
|
||||
await closeWorkerDatabase(sessionId)
|
||||
},
|
||||
runtimeIdentity: runtime,
|
||||
nativeBinding,
|
||||
getVersion: () => getDesktopAppVersion(app.getVersion()),
|
||||
|
||||
@@ -8,6 +8,9 @@ export interface RuntimeRouteContext {
|
||||
pathProvider: PathProvider
|
||||
getVersion: () => string
|
||||
|
||||
/** Close platform-owned database handles before deleting a session. */
|
||||
beforeDeleteSession?: (sessionId: string) => void | Promise<void>
|
||||
|
||||
runtimeIdentity?: RuntimeIdentity
|
||||
/** Native binding path for better-sqlite3 (CLI native copy / Electron-ABI desktop copy). */
|
||||
nativeBinding?: string
|
||||
|
||||
@@ -569,11 +569,20 @@ describe('registerSharedRoutes smoke tests', () => {
|
||||
assert.equal(meta.name, 'Renamed Chat')
|
||||
})
|
||||
|
||||
it('DELETE /_web/sessions/:id delegates to the session adapter', async () => {
|
||||
it('DELETE /_web/sessions/:id closes platform handles before deleting the session', async () => {
|
||||
const db = createSessionDb()
|
||||
const dbs = new Map<string, DatabaseAdapter>([['chat-1', db]])
|
||||
const lifecycle: string[] = []
|
||||
const routeApp = Fastify()
|
||||
registerSessionRoutes(routeApp, createTestContext(dbs))
|
||||
const ctx = createTestContext(dbs)
|
||||
ctx.beforeDeleteSession = async (sessionId) => {
|
||||
lifecycle.push(`close:${sessionId}`)
|
||||
}
|
||||
ctx.sessionAdapter.deleteSessionFile = (sessionId) => {
|
||||
lifecycle.push(`delete:${sessionId}`)
|
||||
return lifecycle[0] === `close:${sessionId}` && dbs.delete(sessionId)
|
||||
}
|
||||
registerSessionRoutes(routeApp, ctx)
|
||||
await routeApp.ready()
|
||||
|
||||
const resp = await routeApp.inject({ method: 'DELETE', url: '/_web/sessions/chat-1' })
|
||||
@@ -584,6 +593,7 @@ describe('registerSharedRoutes smoke tests', () => {
|
||||
assert.equal(resp.statusCode, 200)
|
||||
assert.deepEqual(resp.json(), { success: true })
|
||||
assert.equal(dbs.has('chat-1'), false)
|
||||
assert.deepEqual(lifecycle, ['close:chat-1', 'delete:chat-1'])
|
||||
})
|
||||
|
||||
it('owner profile routes select, apply and dismiss across sessions', async () => {
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { RuntimeRouteContext } from '../../context/runtime'
|
||||
import type { ServiceRouteContext } from '../../context/services'
|
||||
import { sessionService, ownerProfileService, PreferencesManager } from '@openchatlab/node-runtime'
|
||||
|
||||
type SessionRouteContext = Pick<RuntimeRouteContext, 'sessionAdapter' | 'pathProvider'> &
|
||||
type SessionRouteContext = Pick<RuntimeRouteContext, 'sessionAdapter' | 'pathProvider' | 'beforeDeleteSession'> &
|
||||
Pick<ServiceRouteContext, 'preferencesManager'> &
|
||||
Pick<AiRouteContext, 'aiChatManager'>
|
||||
|
||||
@@ -41,6 +41,7 @@ export function registerSessionRoutes(server: FastifyInstance, ctx: SessionRoute
|
||||
server.delete<{ Params: { id: string } }>('/_web/sessions/:id', async (request, reply) => {
|
||||
const { id } = request.params
|
||||
try {
|
||||
await ctx.beforeDeleteSession?.(id)
|
||||
const deleted = sessionService.deleteSession(adapter, id)
|
||||
if (!deleted) {
|
||||
return reply.code(404).send({ success: false, error: 'File not found' })
|
||||
|
||||
Reference in new issue
Block a user