Comments (5)
Reproduction: https://codesandbox.io/p/sandbox/yjs-update-order-7v5pg3?file=%2Findex.js%3A3%2C25
from yjs.
I think the workaround is to check pendingStruct
every time if it's not null. It indicates if a document is broken (because of missing update)
from yjs.
import * as Y from 'yjs'
const doc1 = new Y.Doc()
const doc2 = new Y.Doc()
const doc1Map = doc1.getMap('top')
const doc2Map = doc2.getMap('top')
let updates = []
doc1.on('updateV2', update => {
updates.push(update)
})
// Set initial values on and apply updates to doc 2
doc1Map.set('x', 1)
doc1Map.set('y', 2)
Y.applyUpdateV2(doc2, updates[0])
Y.applyUpdateV2(doc2, updates[1])
updates = []
console.log(doc2Map.toJSON()) // => { x: 1, y: 2 }
// Change two values, but apply updates to doc 2 in reverse order
doc1Map.set('x', 3)
doc1Map.set('y', 4)
Y.applyUpdateV2(doc2, updates[1])
console.log(doc2Map.toJSON()) // => { x: 1 } y is entirely missing!
console.log('pendingStruct', doc2.store.pendingStructs)
Y.applyUpdateV2(doc2, updates[0])
console.log(doc2Map.toJSON()) // => { x: 3, y: 4 }
console.log('pendingStruct', doc2.store.pendingStructs)
[CODESANDBOX] No container config detected
[CODESANDBOX] Running zsh
[CODESANDBOX] Running command: yarn start
yarn run v1.22.19
warning package.json: "test" is also the name of a node core module
$ nodemon index.js
[nodemon] 2.0.20
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node index.js`
{ x: 1, y: 2 }
{ x: 1 }
pendingStruct {
missing: Map(1) { 1669215651 => 2 },
update: Uint8Array(26) [
0, 0, 6, 227, 214, 241, 183, 12,
0, 1, 2, 0, 1, 136, 1, 0,
0, 0, 1, 1, 1, 1, 3, 125,
4, 0
]
}
{ x: 3, y: 4 }
pendingStruct null
[nodemon] clean exit - waiting for changes before restart
In your application logic, you should query the stateVector from missing map
from yjs.
I have made some a script that might can check whether a update would break the data
import { decodeUpdate, decodeUpdateV2, Doc } from 'yjs'
function willMissingUpdateImpl (
doc: Doc,
update: Uint8Array,
decode: typeof decodeUpdateV2 | typeof decodeUpdate
): false | Map<number, number> {
const { structs } = decode(update)
// clientId -> clock
const missingMap = new Map<number, number>()
// find if missing update in the structs
for (let i = 0; i < structs.length; i++) {
const struct = structs[i]
const client = struct.id.client
const items = doc.store.clients.get(client) ?? []
const lastItem = items.at(-1)
if (!lastItem) {
if (struct.id.clock !== 0) {
missingMap.set(client, struct.id.clock)
}
continue
}
const nextClock = lastItem.id.clock + lastItem.length
if (nextClock < struct.id.clock) {
missingMap.set(client, struct.id.clock)
}
}
return missingMap.size > 0 ? missingMap : false
}
export function willMissingUpdate (
doc: Doc, update: Uint8Array): false | Map<number, number> {
return willMissingUpdateImpl(doc, update, decodeUpdate)
}
export function willMissingUpdateV2 (
doc: Doc, update: Uint8Array): false | Map<number, number> {
return willMissingUpdateImpl(doc, update, decodeUpdateV2)
}
from yjs.
The idea is from the applyUpdate
source code; it will check if an update has some missing info before doing the operations.
How to check missing data is easy; just check if the clocks are coherent at the end of each client updates and beginning of the incoming updates
from yjs.
Related Issues (20)
- Is it possible to read uintarray update data? HOT 1
- Merge transactions in undo manager HOT 7
- Mistake in documentation? Property 'set' does not exist on type 'YArray<unknown>'
- Logo as SVG? HOT 4
- RangeError Invalid typed array length: 110 & TypeError: contentRefs[(info & binary.BITS5)] is not a function HOT 2
- Support for TypeScript NodeNext HOT 4
- Inconsistent Y.XmlText.format behavior HOT 1
- support double linked list as a shared data type HOT 1
- Ace binding HOT 1
- y-loopback HOT 2
- UndoManager doesn't persist meta HOT 4
- Froala Editor support HOT 1
- UndoManager stack cleared after a removal on remote side HOT 1
- docs: duplicate Y.Event page entry HOT 1
- Ability to reference UndoManager StackItem inside Type observers
- yText delta attributes is not correct when undo
- Support build for nuxt 2 HOT 1
- Impossible to save a Y.Map when deleted from a Y.Array HOT 5
- Global document undo manager HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from yjs.