diff options
author | Max <max@nextcloud.com> | 2022-10-17 14:08:40 +0300 |
---|---|---|
committer | Max <max@nextcloud.com> | 2022-10-17 16:12:03 +0300 |
commit | 0b8e2600c57ce4be8e020c5ff25a0bea254cefcc (patch) | |
tree | b18aa89a47e9ebaad8d10f5b8d1b0e2640e2379d | |
parent | 70e5a9586933bce6df8fe185e32b4611977afa2e (diff) |
enh: reply to yjs sync step 1 as the serverexperiment/minimal-yjs
The yjs sync protocol has three types of messages:
* Sync step 1 (Question)
* Sync step 2 (Answer)
* Update
The different parties will exchange questions and answers to sync.
Once all parties are synced they exchange updates containing the latest changes.
We used to relay all questions to all parties
which resulted in a lot of unneccessary traffic and db entries.
Instead only store the answers and updates on the server.
Whenever any question comes in reply with the log of all the other messages.
This way questions are only answered once (by the server)
and we can still stick to a "stupid" server
that does not need to understand state vectors and so on.
Signed-off-by: Max <max@nextcloud.com>
-rw-r--r-- | lib/Service/ApiService.php | 4 | ||||
-rw-r--r-- | lib/Service/DocumentService.php | 34 |
2 files changed, 34 insertions, 4 deletions
diff --git a/lib/Service/ApiService.php b/lib/Service/ApiService.php index bf3177dd7..7fc94a025 100644 --- a/lib/Service/ApiService.php +++ b/lib/Service/ApiService.php @@ -177,11 +177,11 @@ class ApiService { $file = $this->documentService->getFileForSession($session, $token); if (!$this->documentService->isReadOnly($file, $token)) { try { - $steps = $this->documentService->addStep($documentId, $sessionId, $steps, $version); + $result = $this->documentService->addStep($documentId, $sessionId, $steps, $version); } catch (InvalidArgumentException $e) { return new DataResponse($e->getMessage(), 422); } - return new DataResponse($steps); + return new DataResponse($result); } return new DataResponse([], 403); } diff --git a/lib/Service/DocumentService.php b/lib/Service/DocumentService.php index fc6d3ff09..d1816e28e 100644 --- a/lib/Service/DocumentService.php +++ b/lib/Service/DocumentService.php @@ -183,9 +183,39 @@ class DocumentService { * @throws InvalidArgumentException */ public function addStep($documentId, $sessionId, $steps, $version): array { + $stepsToInsert = []; + $querySteps = []; + $getStepsSinceVersion = null; + $newVersion = $version; + foreach ($steps as $step) { + if ($step > "AAE") { + array_push($stepsToInsert, $step); + } else { + array_push($querySteps, $step); + } + } + if (sizeof($stepsToInsert) > 0) { + $newVersion = this->insertSteps($documentId, $sessionId, $stepsToInsert, $version); + } + $getStepsSinceVersion = sizeof($querySteps) > 0 ? 0 : $version; + return [ + 'steps' => this->getSteps($documentId, $getStepsSinceVersion), + 'version' => $newVersion + ] + } + + /** + * @param $documentId + * @param $sessionId + * @param $steps + * @param $version + * @return string + * @throws DoesNotExistException + * @throws InvalidArgumentException + */ + private function insertSteps($documentId, $sessionId, $steps, $version): string { $document = null; $stepsVersion = null; - try { $document = $this->documentMapper->find($documentId); $stepsJson = json_encode($steps); @@ -202,7 +232,7 @@ class DocumentService { $step->setVersion($newVersion); $this->stepMapper->insert($step); // TODO write steps to cache for quicker reading - return $steps; + return $newVersion; } catch (DoesNotExistException $e) { throw $e; } catch (\Throwable $e) { |