Skip to content

Commit

Permalink
fixes #832 (#834)
Browse files Browse the repository at this point in the history
* fixes #832

* adds reproduction test
  • Loading branch information
janthurau authored Jun 14, 2024
1 parent fa6d08f commit bfa9b89
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 27 deletions.
4 changes: 2 additions & 2 deletions packages/server/src/DirectConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class DirectConnection implements DirectConnectionInterface {
requestParameters: new URLSearchParams(),
socketId: 'server',
transactionOrigin,
})
}, true)
}

async disconnect() {
Expand All @@ -59,7 +59,7 @@ export class DirectConnection implements DirectConnectionInterface {
requestHeaders: {},
requestParameters: new URLSearchParams(),
socketId: 'server',
})
}, true)

this.document = null
}
Expand Down
53 changes: 28 additions & 25 deletions packages/server/src/Hocuspocus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ export class Hocuspocus {
* "connection" is not necessarily type "Connection", it's the Yjs "origin" (which is "Connection" if
* the update is incoming from the provider, but can be anything if the updates is originated from an extension.
*/
private handleDocumentUpdate(document: Document, connection: Connection | undefined, update: Uint8Array, request?: IncomingMessage): void {
private async handleDocumentUpdate(document: Document, connection: Connection | undefined, update: Uint8Array, request?: IncomingMessage) {
const hookPayload: onChangePayload | onStoreDocumentPayload = {
instance: this,
clientsCount: document.getConnectionsCount(),
Expand All @@ -405,12 +405,7 @@ export class Hocuspocus {
return
}

this.debouncer.debounce(
`onStoreDocument-${document.name}`,
() => this.storeDocumentHooks(document, hookPayload),
this.configuration.debounce,
this.configuration.maxDebounce,
)
await this.storeDocumentHooks(document, hookPayload)
}

/**
Expand Down Expand Up @@ -521,26 +516,34 @@ export class Hocuspocus {
return document
}

storeDocumentHooks(document: Document, hookPayload: onStoreDocumentPayload) {
return this.hooks('onStoreDocument', hookPayload)
.then(() => {
this.hooks('afterStoreDocument', hookPayload).then(() => {
// Remove document from memory.

if (document.getConnectionsCount() > 0) {
return
}
storeDocumentHooks(document: Document, hookPayload: onStoreDocumentPayload, immediately?: boolean) {
return this.debouncer.debounce(
`onStoreDocument-${document.name}`,
() => {
return this.hooks('onStoreDocument', hookPayload)
.then(() => {
this.hooks('afterStoreDocument', hookPayload).then(() => {
// Remove document from memory.

if (document.getConnectionsCount() > 0) {
return
}

this.unloadDocument(document)
})
})
.catch(error => {
console.error('Caught error during storeDocumentHooks', error)

this.unloadDocument(document)
})
})
.catch(error => {
console.error('Caught error during storeDocumentHooks', error)
if (error?.message) {
throw error
}
})
},
immediately ? 0 : this.configuration.debounce,
this.configuration.maxDebounce,
)

if (error?.message) {
throw error
}
})
}

/**
Expand Down
46 changes: 46 additions & 0 deletions tests/server/openDirectConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,3 +218,49 @@ test('direct connection transact awaits until onStoreDocument has finished, even
resolve('done')
})
})

test('creating a websocket connection after transact but before debounce interval doesnt create different docs', async t => {
let onStoreDocumentFinished = false
let disconnected = false

await new Promise(async resolve => {
const server = await newHocuspocus({
onStoreDocument: async () => {
onStoreDocumentFinished = false
await sleep(200)
onStoreDocumentFinished = true
},
async afterUnloadDocument(data) {
console.log('called')
if (disconnected) {
t.fail('must not be called')
}
},
})

const direct = await server.openDirectConnection('hocuspocus-test')
t.is(server.getDocumentsCount(), 1)
t.is(server.getConnectionsCount(), 1)

t.is(onStoreDocumentFinished, false)
await direct.transact(document => {
document.transact(() => {
document.getArray('test').insert(0, ['value'])
}, 'testOrigin')
})
t.is(onStoreDocumentFinished, true)

await direct.disconnect()
disconnected = true

t.is(server.getConnectionsCount(), 0)
t.is(server.getDocumentsCount(), 0)
t.is(onStoreDocumentFinished, true)

const provider = newHocuspocusProvider(server)

await sleep(server.configuration.debounce * 2)

resolve('done')
})
})

0 comments on commit bfa9b89

Please sign in to comment.