refactor: reimplement realtime-communication

This commit refactors a lot of things that are not easy to separate.
It replaces the binary protocol of y-protocols with json.
It introduces event based message processing.
It implements our own code mirror plugins for synchronisation of content and remote cursors

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
Tilman Vatteroth 2023-03-22 20:21:40 +01:00
parent 67cf1432b2
commit 3a06f84af1
110 changed files with 3920 additions and 2201 deletions

View file

@ -0,0 +1,76 @@
/*
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { MessageTransporter, YDocSyncServerAdapter } from '@hedgedoc/commons';
import { Logger } from '@nestjs/common';
import { User } from '../../users/user.entity';
import { generateRandomName } from './random-word-lists/name-randomizer';
import { RealtimeNote } from './realtime-note';
import { RealtimeUserStatusAdapter } from './realtime-user-status-adapter';
/**
* Manages the connection to a specific client.
*/
export class RealtimeConnection {
protected readonly logger = new Logger(RealtimeConnection.name);
private readonly transporter: MessageTransporter;
private readonly yDocSyncAdapter: YDocSyncServerAdapter;
private readonly realtimeUserStateAdapter: RealtimeUserStatusAdapter;
private displayName: string;
/**
* Instantiates the connection wrapper.
*
* @param messageTransporter The message transporter that handles the communication with the client.
* @param user The user of the client
* @param realtimeNote The {@link RealtimeNote} that the client connected to.
* @throws Error if the socket is not open
*/
constructor(
messageTransporter: MessageTransporter,
private user: User | null,
private realtimeNote: RealtimeNote,
) {
this.displayName = user?.displayName ?? generateRandomName();
this.transporter = messageTransporter;
this.transporter.on('disconnected', () => {
realtimeNote.removeClient(this);
});
this.yDocSyncAdapter = new YDocSyncServerAdapter(this.transporter);
this.yDocSyncAdapter.setYDoc(realtimeNote.getRealtimeDoc());
this.realtimeUserStateAdapter = new RealtimeUserStatusAdapter(
this.user?.username ?? null,
this.getDisplayName(),
this,
);
}
public getRealtimeUserStateAdapter(): RealtimeUserStatusAdapter {
return this.realtimeUserStateAdapter;
}
public getTransporter(): MessageTransporter {
return this.transporter;
}
public getUser(): User | null {
return this.user;
}
public getSyncAdapter(): YDocSyncServerAdapter {
return this.yDocSyncAdapter;
}
public getDisplayName(): string {
return this.displayName;
}
public getRealtimeNote(): RealtimeNote {
return this.realtimeNote;
}
}