Change room with y-webrtc

Hello,
I want users to collaborate on different documents via peer-to-peer communication (y-webrtc).

My understanding is that I need to create a different room for each document. In this setup, when a user switches from one document to another, they would to have to change the room.

I couldn’t find an option to change the room in the WebrtcProvider. So, I figured that I might have to create a new WebrtcProvider whenever the user switches to another document (webrtc = webrtcProvider(documentId, new Doc());).

Yet, when I do this, I receive these errors:

    Error: A Yjs Doc connected to room "document1" already exists!
        at Module.create (error.js:12)
        at openRoom (y-webrtc.js:437)
        at y-webrtc.js:574

Looking through the code, I see that y-webrtc remembers the room, and prevent to subscribe multiple times to the same room. Yet, I don’t really understand how to switch the room (or how to subscribe to multiple room and figure out for which room data in a change event is).

I’d highly appreciate a pointer on how to handle this?

Thanks a lot!

1 Like

Hi @roro,

You are right, when using y-webrtc you can only subscribe to a room at most once. With the other providers, you can subscribe to the same room several times at the same time. Ideally though, you subscribe to a room only once and reuse subscribed documents.

y-webrtc reuses signaling connections for all rooms. It is pretty hard to manage multiple connections over a shared signaling server, so I simply forbid that case to make it easier for me. Note that while the provider is active, you still listen to document updates and keep the document state in-memory. So when you are done with a connection (e.g. the user switches to a different document), you can simply destroy the connection webrtcProvider.destroy(). After you destroyed the connection, you can reconnect to the same room again.

Hope that helps.
– Kevin

Thanks a lot, Kevin. This is very helpful!

Hi Kevin,

I have problem with y-webrtc change room, too. But my problem is after changing the room, the collaboration cursor is not shown in peers’ codemirror 6 editors.

My project is very simple, just using JS. Here is generally what I did.

import * as Y from 'yjs';

// @ts-ignore
import { yCollab, yUndoManagerKeymap } from 'y-codemirror.next';
import { WebrtcProvider } from 'y-webrtc';

...
// Create a codemirrow 6 editor
const collabConfig = new Compartment();

const ydoc = new Y.Doc();
let provider = new WebrtcProvider('codemirror6-room-' + random.uint32(), ydoc, { signaling: [signalingServerUri]}); // Each user starts in a separate room at beginning
let ytext = ydoc.getText();

provider.awareness.setLocalStateField('user', {
    name: username + ' ' + Math.floor(Math.random() * 100),
    color: userColor.color,
    colorLight: userColor.light
});

let extensions = [
...
collabConfig.of(yCollab(ytext, provider.awareness))
];
let state = EditorState.create({ "doc": ytext.toString(), "extensions": extensions });
let editor = new EditorView({ state, parent: document.querySelector("#editor") });

// I put a link in the web page. If user clicks that link, the user will change to a fixed room
document.querySelectorAll("a.editable").forEach((file) => {
    file.addEventListener("click", function(event){
        event.preventDefault();

        // The room could be changed with some lines of code commented out.
        // The only problem I have is I could not see coloured cursors in peers' editor 

        // ydoc = new Y.Doc(); // Uncomment this line, the collaboration won't work
        // ytext = ydoc.getText();
        provider.disconnect(); // Have to destroy the existing connection, then the connection could be rebuilt.
        provider = new WebrtcProvider(filePath.replace(/\//g, '').replace('.', ''), ydoc, { signaling: [signalingServerUri]});
        provider.awareness.setLocalStateField('user', {
            name: username + ' ' + Math.floor(Math.random() * 100),
            color: userColor.color,
            colorLight: userColor.light
        });
        // editor.dispatch({
        //     annotations: [collabConfig.reconfigure(yCollab(ytext, provider.awareness))]
        // });
    });
});

Any feedback is appreciated. Thanks.

I think I figured that out.

First uncomment those lines of code, then use editor.setState instead of editor.dispatch to reset the editor. And then everything works.

So this should be a codemirror 6 problem, not yjs.