Discussions related to Shared Editing, Distributed Apps, and Yjs. Questions about Yjs should go to discuss.yjs.dev. Bug reports to the issue tracker.
yjs
with vis-network
to manage and display a graph at https://github.com/micrology/y-vis-network . This is just a skeleton example. For the full works, see https://prsm.uk and the code at https://github.com/micrology/prsm (for the interaction with yjs
, see the top of https://github.com/micrology/prsm/blob/master/js/prsm.js
content
field.ContentDeleted
/GC
objects.Reading through the paper for YATA it mentions that it can be used for graphs. Is there an example of this? From what I could figure people usually have a map of nodes and a map of edges. With that that though, what happens if someone removes a node (and all connecting edges) in their client and another client adds an edge to that node? It seems like the new edge would still be added. This seems like it would be an issue with any piece of data that had multiple parents (as otherwise they could just be put in a map). I could imagine a garbage collector that would check and remove these as the changes came in, but is there a better way? Guessing that a graph like that (or tabular data) could be implemented as types...
@rhysbrettbowen can a possible solution be to perform edge-garbage-collection each time an edge is created?
Hey everyone! I have two Yjs docs connected via the webrtc provider sharing a Map type. When I set a property foo
on device A, device B updates perfectly. However when I set foo
on device B now, it is deleted on A (as shown by my observe event on the Map and the update
on the doc). Note the order of changing foo
on A & B doesn't make a difference.
I have tried creating a simple example script but never can reproduce the desync. Any suggestions on how to debug how the two docs get out of sync? Are there any common scenarios that can cause this?
separately if i have a queue of updates and want to flatten them to save space is there an easy way? and does that then become a snapshot other changes are based off of?
@nc the way y-leveldb persistence does it is by merging the updates queue into a single update when fetching the updates from the db. I use the same mechanism in my relational db backed y-websocket backend https://github.com/kapv89/yjs-scalable-ws-backend/blob/main/src/setupWSConnection.ts#L133-L156
Hi Everyone, I've been playing around with yjs and enjoying it so far :)
I've found that a nested text inside a map behaves differently to a top level text, which is surprising to me.
Here's the behaviour with two top level texts:
aText current state aaaaaa
bText current state bbbbbb
insert into aText 'AAA" at 2
insert into bText 'BBB' at 2
apply updates to both
adoc latest state bbBBBbbbbaaAAAaaaa
bdoc latest state bbBBBbbbbaaAAAaaaa
This makes sense to me - both texts end up with the combined inserts.
Whereas with a nested text inside a map:
aMap current state { 'my nested text': 'aaaaaa' }
bMap current state { 'my nested text': 'bbbbbb' }
insert into a nested text 'AAA" at 2
insert into b nested text 'BBB' at 2
apply updates to both
aMap latest state { 'my nested text': 'bbBBBbbbb' }
bMap latest state { 'my nested text': 'bbBBBbbbb' }
They randomly converge on either the text from A, or B, instead of including the changes from both.
This makes me feel like I've incorrectly set up my nested text inside my map. Happy to show my code, but I wanted to check as I couldn't find any conclusive statements in the docs beyond my intuition - the nested text state in my second example should end up looking just like the top level text in my first example, right? (otherwise there'd be little point nesting shared types)
I used the docs for Y.Text that has an example of a nested text for my inspiration, but the docs don't actually show it being updated and being propagated across multiple document instances
https://docs.yjs.dev/api/shared-types/y.text
Are there any other examples of nested text in the docs or demos?
Thanks :)
I've found that a nested text inside a map behaves differently to a top level text, which is surprising to me.
Here's the behaviour with two top level texts:
I solved my problem - it turns out that creating two Texts separately under the same key are treated as completely separate things - the key is not their identity, they are. The only safe way to collaboratively edit the same text is to create it on one document, and replicate it to the others by sending state as an update, then editing it afterwards!
Thanks, that makes a lot of sense and is something I'll bear in mind for the future!
Hello! I'm having a bit of trouble understanding the actual usage pattern of yjs from a macro standpoint. I'm not using nodejs for my server, but I could theoeretically call out to a managed nodejs process from my backend server, something I've set up for SSR already. I already have websocket connections set up from my clients to my server. Is there some way that I could use yjs on the clients, managed from a non-js server without having to involve nodejs server side?
@zachdaniel you can take a look at this repo https://github.com/kapv89/yjs-scalable-ws-backend and modify it to interact with an api instead of interacting directly with the db, and then have your actual api-backend in any language of your choice
That would be surprising to me too! The hard drive is an SSD. Does anyone else have any data on this?
Related to this, I am using both y-websocket and y-indexeddb. The README says
y-websocket
A module that contains a simple websocket backend and a websocket client that connects to that backend. The backend can be extended to persist updates in a leveldb database.
y-indexeddb
Efficiently persists document updates to the browsers indexeddb database. The document is immediately available and only diffs need to be synced through the network provider.from which I concluded that y-indexeddb (which uses the local client) should sync faster than y-websocket (the websocket server is in Ireland and I am in England). But I always find that the websocket provider syncs first, by a few milliseconds. Why?
The code looks like this (
exactTime()
yields the time now to the nearest millisecond):const doc = new Y.Doc(); const persistence = new IndexeddbPersistence(room, doc); persistence.once('synced', () => { console.log(exactTime() + ' local content loaded'); }); const wsProvider = new WebsocketProvider(websocket, 'prsm' + room, doc); wsProvider.on('sync', () => { console.log(exactTime() + ' remote content loaded'); }); yNodesMap = doc.getMap('nodes'); yEdgesMap = doc.getMap('edges');
Example output:
09:49:47:513 remote content loaded 09:49:47:516 local content loaded
I believe y-websocket implemented with a bug which did not wait both side exchange the initial vector, then sent out the initial empty data to client, then client thought it is "synced" but indeed the server side did not load the yjs doc from leveldb yet.
Hi, is there a way to delete a root type? Can't find a way to do it..
Essentially the same as:
const info = ydoc.getMap('info')
const value = new Y.Array()
value.insert(0, [1,2,3])
info.set('foo', value)
info.delete('foo')
But using a root type:
const foo = ydoc.getArray('info/foo')
foo.insert(0, [1,2,3])
// How to delete when I don't need this array anymore?