mirror of
https://github.com/langgenius/dify.git
synced 2026-08-28 22:36:52 +08:00
Merge a75256fc51 into dfac3e524e
This commit is contained in:
commit
302b503800
@ -49,11 +49,10 @@ describe('CollaborationManager CRDT runtime loading', () => {
|
||||
expect(manager.isConnected()).toBe(false)
|
||||
})
|
||||
|
||||
it('does not create connection state when the runtime fails to load and allows a retry', async () => {
|
||||
it('falls back to local editing instead of leaving the UI stuck when the runtime fails to load', async () => {
|
||||
const { CollaborationManager, webSocketClient } = await loadCollaborationModules()
|
||||
const manager = new CollaborationManager()
|
||||
const runtimeError = new Error('runtime-load-failed')
|
||||
const retryError = new Error('runtime-retry-failed')
|
||||
const loadRuntimeSpy = vi
|
||||
.spyOn(
|
||||
manager as unknown as {
|
||||
@ -62,19 +61,44 @@ describe('CollaborationManager CRDT runtime loading', () => {
|
||||
'loadCrdtRuntime',
|
||||
)
|
||||
.mockRejectedValueOnce(runtimeError)
|
||||
.mockRejectedValueOnce(retryError)
|
||||
const connectSpy = vi.spyOn(webSocketClient, 'connect')
|
||||
|
||||
await expect(manager.connect('app-runtime-failure')).rejects.toBe(runtimeError)
|
||||
const connectionId = await manager.connect('app-runtime-failure')
|
||||
|
||||
expect(loadRuntimeSpy).toHaveBeenCalledTimes(1)
|
||||
expect(connectSpy).not.toHaveBeenCalled()
|
||||
expect(manager.isConnected()).toBe(false)
|
||||
expect(manager.canApplyLocalGraphMutation()).toBe(true)
|
||||
expect(manager.canPersistLocalGraph()).toBe(true)
|
||||
|
||||
await expect(manager.connect('app-runtime-failure')).rejects.toBe(retryError)
|
||||
manager.disconnect(connectionId)
|
||||
})
|
||||
|
||||
expect(loadRuntimeSpy).toHaveBeenCalledTimes(2)
|
||||
it('keeps editing blocked when the runtime fails to load on a configured socket URL', async () => {
|
||||
const { CollaborationManager } = await loadCollaborationModules()
|
||||
const websocketManager = await import('../websocket-manager')
|
||||
vi.spyOn(websocketManager, 'isDefaultSocketUrl').mockReturnValue(false)
|
||||
const manager = new CollaborationManager()
|
||||
const runtimeError = new Error('runtime-load-failed')
|
||||
const loadRuntimeSpy = vi
|
||||
.spyOn(
|
||||
manager as unknown as {
|
||||
loadCrdtRuntime: () => Promise<(typeof import('../crdt-runtime'))['crdtRuntime']>
|
||||
},
|
||||
'loadCrdtRuntime',
|
||||
)
|
||||
.mockRejectedValueOnce(runtimeError)
|
||||
const connectSpy = vi.spyOn(websocketManager.webSocketClient, 'connect')
|
||||
|
||||
const connectionId = await manager.connect('app-runtime-failure-configured-socket')
|
||||
|
||||
expect(loadRuntimeSpy).toHaveBeenCalledTimes(1)
|
||||
expect(connectSpy).not.toHaveBeenCalled()
|
||||
expect(manager.isConnected()).toBe(false)
|
||||
expect(manager.canApplyLocalGraphMutation()).toBe(false)
|
||||
expect(manager.canPersistLocalGraph()).toBe(false)
|
||||
|
||||
manager.disconnect(connectionId)
|
||||
})
|
||||
|
||||
it('initializes one session for concurrent consumers of the same app', async () => {
|
||||
|
||||
@ -664,7 +664,24 @@ export class CollaborationManager {
|
||||
}
|
||||
const connectGeneration = this.connectGeneration
|
||||
|
||||
if (!this.crdtRuntime) await this.ensureCrdtRuntime()
|
||||
if (!this.crdtRuntime) {
|
||||
try {
|
||||
await this.ensureCrdtRuntime()
|
||||
} catch (error) {
|
||||
console.error('Failed to load collaboration runtime, falling back to local editing:', error)
|
||||
if (connectGeneration === this.connectGeneration && this.targetAppId === appId) {
|
||||
this.currentAppId = appId
|
||||
// Mirrors activateLocalDraftFallback(): only degrade to local-only editing on the
|
||||
// default self-hosted socket URL. A configured (Cloud/Enterprise) socket implies a real
|
||||
// collaboration server may have other users editing live, so editing stays blocked here.
|
||||
if (isDefaultSocketUrl() && !this.hasEstablishedConnection)
|
||||
this.localDraftFallbackActive = true
|
||||
this.activeConnections.add(connectionId)
|
||||
this.emitGraphReadyState()
|
||||
}
|
||||
return connectionId
|
||||
}
|
||||
}
|
||||
|
||||
if (connectGeneration !== this.connectGeneration || this.targetAppId !== appId)
|
||||
return connectionId
|
||||
|
||||
Loading…
Reference in New Issue
Block a user