refacto(backend): new backend WhiteboardInfoBackendService

* WhiteboardInfo set private inside this module
This commit is contained in:
Florent Chehab 2020-05-12 22:33:33 +02:00
parent 99e5bb0d98
commit 3844d08bdd
No known key found for this signature in database
GPG Key ID: 9A0CE018889EA246
3 changed files with 207 additions and 157 deletions

View File

@ -1,106 +0,0 @@
const config = require("./config/config");
/**
* Class to hold information related to a whiteboard
*/
class WhiteboardServerSideInfo {
static defaultScreenResolution = { w: 1000, h: 1000 };
/**
* @type {number}
* @private
*/
#nbConnectedUsers = 0;
get nbConnectedUsers() {
return this.#nbConnectedUsers;
}
/**
* @type {Map<int, {w: number, h: number}>}
* @private
*/
#screenResolutionByClients = new Map();
get screenResolutionByClients() {
return this.#screenResolutionByClients;
}
/**
* Variable to tell if these info have been sent or not
*
* @private
* @type {boolean}
*/
#hasNonSentUpdates = false;
get hasNonSentUpdates() {
return this.#hasNonSentUpdates;
}
incrementNbConnectedUsers() {
this.#nbConnectedUsers++;
this.#hasNonSentUpdates = true;
}
decrementNbConnectedUsers() {
this.#nbConnectedUsers--;
this.#hasNonSentUpdates = true;
}
hasConnectedUser() {
return this.#nbConnectedUsers > 0;
}
/**
* Store information about the client's screen resolution
*
* @param {number} clientId
* @param {number} w client's width
* @param {number} h client's hight
*/
setScreenResolutionForClient(clientId, { w, h }) {
this.#screenResolutionByClients.set(clientId, { w, h });
this.#hasNonSentUpdates = true;
}
/**
* Delete the stored information about the client's screen resoltion
* @param clientId
*/
deleteScreenResolutionOfClient(clientId) {
this.#screenResolutionByClients.delete(clientId);
this.#hasNonSentUpdates = true;
}
/**
* Get the smallest client's screen size on a whiteboard
* @return {{w: number, h: number}}
*/
getSmallestScreenResolution() {
const { screenResolutionByClients: resolutions } = this;
return {
w: Math.min(...Array.from(resolutions.values()).map((res) => res.w)),
h: Math.min(...Array.from(resolutions.values()).map((res) => res.h)),
};
}
infoWasSent() {
this.#hasNonSentUpdates = false;
}
shouldSendInfo() {
return this.#hasNonSentUpdates;
}
asObject() {
const out = {
nbConnectedUsers: this.#nbConnectedUsers,
};
if (config.frontend.showSmallestScreenIndicator) {
out.smallestScreenResolution = this.getSmallestScreenResolution();
}
return out;
}
}
module.exports = WhiteboardServerSideInfo;

View File

@ -1,8 +1,8 @@
const path = require("path");
const config = require("./config/config");
const WhiteboardServerSideInfo = require("./WhiteboardServerSideInfo");
const ReadOnlyBackendService = require("./services/ReadOnlyBackendService");
const WhiteboardInfoBackendService = require("./services/WhiteboardInfoBackendService");
function startBackendServer(port) {
var fs = require("fs-extra");
@ -24,6 +24,8 @@ function startBackendServer(port) {
var server = require("http").Server(app);
server.listen(port);
var io = require("socket.io")(server, { path: "/ws-api" });
WhiteboardInfoBackendService.start(io);
console.log("Webserver & socketserver running on port:" + port);
const { accessToken, enableWebdav } = config.backend;
@ -180,41 +182,11 @@ function startBackendServer(port) {
}
}
/**
* @type {Map<string, WhiteboardServerSideInfo>}
*/
const infoByWhiteboard = new Map();
setInterval(() => {
infoByWhiteboard.forEach((info, whiteboardId) => {
if (info.shouldSendInfo()) {
io.sockets
.in(whiteboardId)
.compress(false)
.emit("whiteboardInfoUpdate", info.asObject());
info.infoWasSent();
}
});
}, (1 / config.backend.performance.whiteboardInfoBroadcastFreq) * 1000);
io.on("connection", function (socket) {
let whiteboardId = null;
socket.on("disconnect", function () {
if (infoByWhiteboard.has(whiteboardId)) {
const whiteboardServerSideInfo = infoByWhiteboard.get(whiteboardId);
if (socket && socket.id) {
whiteboardServerSideInfo.deleteScreenResolutionOfClient(socket.id);
}
whiteboardServerSideInfo.decrementNbConnectedUsers();
if (whiteboardServerSideInfo.hasConnectedUser()) {
socket.compress(false).broadcast.emit("refreshUserBadges", null); //Removes old user Badges
} else {
infoByWhiteboard.delete(whiteboardId);
}
}
WhiteboardInfoBackendService.disconnect(socket.id, whiteboardId);
socket.compress(false).broadcast.to(whiteboardId).emit("refreshUserBadges", null); //Removes old user Badges
});
socket.on("drawToWhiteboard", function (content) {
@ -226,12 +198,9 @@ function startBackendServer(port) {
socket.compress(false).broadcast.to(wid).emit("drawToWhiteboard", content);
// broadcast to current whiteboard
broadcastTo(whiteboardId);
// broadcast the same content to the associated read-only whiteboard
const readOnlyId = ReadOnlyBackendService.getReadOnlyId(whiteboardId);
const readOnlyWhiteboardInfo = infoByWhiteboard.get(readOnlyId);
if (readOnlyWhiteboardInfo && readOnlyWhiteboardInfo.hasConnectedUser()) {
// broadcast the same content to the associated read-only whiteboard
broadcastTo(readOnlyId);
}
broadcastTo(readOnlyId);
s_whiteboard.handleEventsAndData(content); //save whiteboardchanges on the server
} else {
socket.emit("wrongAccessToken", true);
@ -254,16 +223,8 @@ function startBackendServer(port) {
});
socket.join(whiteboardId); //Joins room name=wid
if (!infoByWhiteboard.has(whiteboardId)) {
infoByWhiteboard.set(whiteboardId, new WhiteboardServerSideInfo());
}
const whiteboardServerSideInfo = infoByWhiteboard.get(whiteboardId);
whiteboardServerSideInfo.incrementNbConnectedUsers();
whiteboardServerSideInfo.setScreenResolutionForClient(
socket.id,
content["windowWidthHeight"] || WhiteboardServerSideInfo.defaultScreenResolution
);
const screenResolution = content["windowWidthHeight"];
WhiteboardInfoBackendService.join(socket.id, whiteboardId, screenResolution);
} else {
socket.emit("wrongAccessToken", true);
}
@ -272,10 +233,11 @@ function startBackendServer(port) {
socket.on("updateScreenResolution", function (content) {
content = escapeAllContentStrings(content);
if (accessToken === "" || accessToken == content["at"]) {
const whiteboardServerSideInfo = infoByWhiteboard.get(whiteboardId);
whiteboardServerSideInfo.setScreenResolutionForClient(
const screenResolution = content["windowWidthHeight"];
WhiteboardInfoBackendService.setScreenResolution(
socket.id,
content["windowWidthHeight"] || WhiteboardServerSideInfo.defaultScreenResolution
whiteboardId,
screenResolution
);
}
});

View File

@ -0,0 +1,194 @@
const config = require("../config/config");
/**
* Class to hold information related to a whiteboard
*/
class WhiteboardInfo {
static defaultScreenResolution = { w: 1000, h: 1000 };
/**
* @type {number}
* @private
*/
#nbConnectedUsers = 0;
get nbConnectedUsers() {
return this.#nbConnectedUsers;
}
/**
* @type {Map<string, {w: number, h: number}>}
* @private
*/
#screenResolutionByClients = new Map();
get screenResolutionByClients() {
return this.#screenResolutionByClients;
}
/**
* Variable to tell if these info have been sent or not
*
* @private
* @type {boolean}
*/
#hasNonSentUpdates = false;
get hasNonSentUpdates() {
return this.#hasNonSentUpdates;
}
incrementNbConnectedUsers() {
this.#nbConnectedUsers++;
this.#hasNonSentUpdates = true;
}
decrementNbConnectedUsers() {
this.#nbConnectedUsers--;
this.#hasNonSentUpdates = true;
}
hasConnectedUser() {
return this.#nbConnectedUsers > 0;
}
/**
* Store information about the client's screen resolution
*
* @param {string} clientId
* @param {number} w client's width
* @param {number} h client's hight
*/
setScreenResolutionForClient(clientId, { w, h }) {
this.#screenResolutionByClients.set(clientId, { w, h });
this.#hasNonSentUpdates = true;
}
/**
* Delete the stored information about the client's screen resoltion
* @param clientId
*/
deleteScreenResolutionOfClient(clientId) {
this.#screenResolutionByClients.delete(clientId);
this.#hasNonSentUpdates = true;
}
/**
* Get the smallest client's screen size on a whiteboard
* @return {{w: number, h: number}}
*/
getSmallestScreenResolution() {
const { screenResolutionByClients: resolutions } = this;
return {
w: Math.min(...Array.from(resolutions.values()).map((res) => res.w)),
h: Math.min(...Array.from(resolutions.values()).map((res) => res.h)),
};
}
infoWasSent() {
this.#hasNonSentUpdates = false;
}
shouldSendInfo() {
return this.#hasNonSentUpdates;
}
asObject() {
const out = {
nbConnectedUsers: this.#nbConnectedUsers,
};
if (config.frontend.showSmallestScreenIndicator) {
out.smallestScreenResolution = this.getSmallestScreenResolution();
}
return out;
}
}
class WhiteboardInfoBackendService {
/**
* @type {Map<string, WhiteboardInfo>}
*/
#infoByWhiteboard = new Map();
/**
* Start the auto sending of information to all the whiteboards
*
* @param io
*/
start(io) {
// auto clean infoByWhiteboard
setInterval(() => {
this.#infoByWhiteboard.forEach((info, whiteboardId) => {
if (info.shouldSendInfo()) {
io.sockets
.in(whiteboardId)
.compress(false)
.emit("whiteboardInfoUpdate", info.asObject());
info.infoWasSent();
}
});
}, (1 / config.backend.performance.whiteboardInfoBroadcastFreq) * 1000);
}
/**
* Track a join event of client to a whiteboard
*
* @param {string} clientId
* @param {string} whiteboardId
* @param {{w: number, h: number}} screenResolution
*/
join(clientId, whiteboardId, screenResolution) {
const infoByWhiteboard = this.#infoByWhiteboard;
if (!infoByWhiteboard.has(whiteboardId)) {
infoByWhiteboard.set(whiteboardId, new WhiteboardInfo());
}
const whiteboardServerSideInfo = infoByWhiteboard.get(whiteboardId);
whiteboardServerSideInfo.incrementNbConnectedUsers();
this.setScreenResolution(clientId, whiteboardId, screenResolution);
}
/**
* Set the screen resolution of a client
* @param {string} clientId
* @param {string} whiteboardId
* @param {{w: number, h: number}} screenResolution
*/
setScreenResolution(clientId, whiteboardId, screenResolution) {
const infoByWhiteboard = this.#infoByWhiteboard;
const whiteboardServerSideInfo = infoByWhiteboard.get(whiteboardId);
if (whiteboardServerSideInfo) {
whiteboardServerSideInfo.setScreenResolutionForClient(
clientId,
screenResolution || WhiteboardInfo.defaultScreenResolution
);
}
}
/**
* Track disconnect from a client
* @param {string} clientId
* @param {string} whiteboardId
*/
disconnect(clientId, whiteboardId) {
const infoByWhiteboard = this.#infoByWhiteboard;
if (infoByWhiteboard.has(whiteboardId)) {
const whiteboardServerSideInfo = infoByWhiteboard.get(whiteboardId);
if (clientId) {
whiteboardServerSideInfo.deleteScreenResolutionOfClient(clientId);
}
whiteboardServerSideInfo.decrementNbConnectedUsers();
if (whiteboardServerSideInfo.hasConnectedUser()) {
} else {
infoByWhiteboard.delete(whiteboardId);
}
}
}
}
module.exports = new WhiteboardInfoBackendService();