Skip to content

Commit

Permalink
Merge pull request #6696 from nextcloud/backport/6650/stable29
Browse files Browse the repository at this point in the history
[stable29] Send one full update from y-websocket
  • Loading branch information
mejo- authored Nov 27, 2024
2 parents 61df46f + 9874d6f commit 03d88e0
Show file tree
Hide file tree
Showing 21 changed files with 768 additions and 937 deletions.
32 changes: 7 additions & 25 deletions cypress/component/helpers/yjs.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
*/

import * as Y from 'yjs'
import { getDocumentState, getUpdateMessage, applyUpdateMessage } from '../../../src/helpers/yjs.js'
import { getDocumentState, documentStateToStep, applyStep } from '../../../src/helpers/yjs.js'

describe('Yjs base64 wrapped with our helpers', function() {
it('applies step in wrong order', function() {
it('applies step generated from document state', function() {
const source = new Y.Doc()
const target = new Y.Doc()
const sourceMap = source.getMap()
Expand All @@ -34,44 +34,26 @@ describe('Yjs base64 wrapped with our helpers', function() {
// console.log('afterTransaction', tr)
})

const state0 = getDocumentState(source)

// Add keyA to source and apply to target
sourceMap.set('keyA', 'valueA')

const stateA = getDocumentState(source)
const update0A = getUpdateMessage(source, state0)
applyUpdateMessage(target, update0A)
const step0A = documentStateToStep(stateA)
applyStep(target, step0A)
expect(targetMap.get('keyA')).to.be.eq('valueA')

// Add keyB to source, don't apply to target yet
sourceMap.set('keyB', 'valueB')
const stateB = getDocumentState(source)
const updateAB = getUpdateMessage(source, stateA)
const step0B = documentStateToStep(stateB)

// Add keyC to source, apply to target
sourceMap.set('keyC', 'valueC')
const updateBC = getUpdateMessage(source, stateB)
applyUpdateMessage(target, updateBC)
expect(targetMap.get('keyB')).to.be.eq(undefined)
expect(targetMap.get('keyC')).to.be.eq(undefined)

// Apply keyB to target
applyUpdateMessage(target, updateAB)
applyStep(target, step0B)
expect(targetMap.get('keyB')).to.be.eq('valueB')
expect(targetMap.get('keyC')).to.be.eq('valueC')
})

it('update message is empty if no additional state exists', function() {
const source = new Y.Doc()
const sourceMap = source.getMap()
const state0 = getDocumentState(source)
sourceMap.set('keyA', 'valueA')
const stateA = getDocumentState(source)
const update0A = getUpdateMessage(source, state0)
const updateAA = getUpdateMessage(source, stateA)
expect(update0A.length).to.be.eq(29)
expect(updateAA).to.be.eq(undefined)
expect(targetMap.get('keyC')).to.be.eq(undefined)
})

})
3 changes: 3 additions & 0 deletions cypress/e2e/api/SyncServiceProvider.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
*/

import { randUser } from '../../utils/index.js'
import SessionApi from '../../../src/services/SessionApi.js'
import { SyncService } from '../../../src/services/SyncService.js'
import createSyncServiceProvider from '../../../src/services/SyncServiceProvider.js'
import { Doc } from 'yjs'
Expand Down Expand Up @@ -56,9 +57,11 @@ describe('Sync service provider', function() {
*/
function createProvider(ydoc) {
const queue = []
const api = new SessionApi()
const syncService = new SyncService({
serialize: () => 'Serialized',
getDocumentState: () => null,
api,
})
syncService.on('opened', () => syncService.startSync())
return createSyncServiceProvider({
Expand Down
3 changes: 3 additions & 0 deletions cypress/e2e/directediting.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import { initUserAndFiles, randUser } from '../utils/index.js'

const user = randUser()

/**
* Enter content and close
*/
function enterContentAndClose() {
cy.intercept({ method: 'POST', url: '**/session/*/close' }).as('closeRequest')
cy.intercept({ method: 'POST', url: '**/session/*/push' }).as('push')
Expand Down
6 changes: 6 additions & 0 deletions cypress/e2e/nodes/Links.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ describe('test link marks', function() {

describe('link bubble', function() {

/**
* Find link and click on it
*
* @param {string} link The link URL
* @param {object|null} options the click options
*/
function clickLink(link, options = {}) {
cy.getContent()
.find(`a[href*="${link}"]`)
Expand Down
2 changes: 1 addition & 1 deletion cypress/e2e/nodes/Preview.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ describe('Preview extension', { retries: 0 }, () => {

/**
*
* @param input
* @param {string} input the markdown content
*/
function prepareEditor(input) {
loadMarkdown(editor, input)
Expand Down
14 changes: 7 additions & 7 deletions cypress/e2e/nodes/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ import { createMarkdownSerializer } from './../../../src/extensions/Markdown.js'

/**
*
* @param editor
* @param markdown
* @param {object} editor the editor object
* @param {string} markdown the markdown content
*/
export function loadMarkdown(editor, markdown) {
const stripped = markdown.replace(/\t*/g, '')
Expand All @@ -36,7 +36,7 @@ export function loadMarkdown(editor, markdown) {

/**
*
* @param editor
* @param {object} editor the editor object
*/
export function runCommands(editor) {
let found
Expand All @@ -51,7 +51,7 @@ export function runCommands(editor) {

/**
*
* @param editor
* @param {object} editor the editor object
*/
function findCommand(editor) {
const doc = editor.state.doc
Expand All @@ -62,8 +62,8 @@ function findCommand(editor) {

/**
*
* @param editor
* @param markdown
* @param {object} editor the editor object
* @param {string} markdown the markdown content
*/
export function expectMarkdown(editor, markdown) {
const stripped = markdown.replace(/\t*/g, '')
Expand All @@ -72,7 +72,7 @@ export function expectMarkdown(editor, markdown) {

/**
*
* @param editor
* @param {object} editor the editor object
*/
function getMarkdown(editor) {
const serializer = createMarkdownSerializer(editor.schema)
Expand Down
29 changes: 24 additions & 5 deletions lib/Service/DocumentService.php
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,8 @@ public function addStep(Document $document, Session $session, array $steps, int
$documentId = $session->getDocumentId();
$readOnly = $this->isReadOnly($this->getFileForSession($session, $shareToken), $shareToken);
$stepsToInsert = [];
$querySteps = [];
$stepsIncludeQuery = false;
$documentState = null;
$newVersion = $version;
foreach ($steps as $step) {
$message = YjsMessage::fromBase64($step);
Expand All @@ -234,7 +235,7 @@ public function addStep(Document $document, Session $session, array $steps, int
}
// Filter out query steps as they would just trigger clients to send their steps again
if ($message->getYjsMessageType() === YjsMessage::YJS_MESSAGE_SYNC && $message->getYjsSyncType() === YjsMessage::YJS_MESSAGE_SYNC_STEP1) {
$querySteps[] = $step;
$stepsIncludeQuery = true;
} else {
$stepsToInsert[] = $step;
}
Expand All @@ -245,8 +246,24 @@ public function addStep(Document $document, Session $session, array $steps, int
}
$newVersion = $this->insertSteps($document, $session, $stepsToInsert);
}
// If there were any queries in the steps send the entire history
$getStepsSinceVersion = count($querySteps) > 0 ? 0 : $version;

// By default send all steps the user has not received yet.
$getStepsSinceVersion = $version;
if ($stepsIncludeQuery) {
$this->logger->debug('Loading document state for ' . $documentId);
try {
$stateFile = $this->getStateFile($documentId);
$documentState = $stateFile->getContent();
$this->logger->debug('Existing document, state file loaded ' . $documentId);
// If there were any queries in the steps send all steps since last save.
$getStepsSinceVersion = $document->getLastSavedVersion();
} catch (NotFoundException $e) {
$this->logger->debug('Existing document, but no state file found for ' . $documentId);
// If there is no state file include all the steps.
$getStepsSinceVersion = 0;
}
}

$allSteps = $this->getSteps($documentId, $getStepsSinceVersion);
$stepsToReturn = [];
foreach ($allSteps as $step) {
Expand All @@ -255,9 +272,11 @@ public function addStep(Document $document, Session $session, array $steps, int
$stepsToReturn[] = $step;
}
}

return [
'steps' => $stepsToReturn,
'version' => $newVersion
'version' => $newVersion,
'documentState' => $documentState
];
}

Expand Down
Loading

0 comments on commit 03d88e0

Please sign in to comment.