Kaynağa Gözat

feat: rewrite collab server connecting (#4881)

Co-authored-by: dwelle <luzar.david@gmail.com>
Milos Vetesnik 3 yıl önce
ebeveyn
işleme
5ca4f5bbf4

+ 1 - 1
.env.development

@@ -4,5 +4,5 @@ REACT_APP_BACKEND_V2_POST_URL=https://json-dev.excalidraw.com/api/v2/post/
 REACT_APP_LIBRARY_URL=https://libraries.excalidraw.com
 REACT_APP_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries
 
-REACT_APP_SOCKET_SERVER_URL=http://localhost:3002
+REACT_APP_PORTAL_URL=http://localhost:3002
 REACT_APP_FIREBASE_CONFIG='{"apiKey":"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8","authDomain":"excalidraw-oss-dev.firebaseapp.com","projectId":"excalidraw-oss-dev","storageBucket":"excalidraw-oss-dev.appspot.com","messagingSenderId":"664559512677","appId":"1:664559512677:web:a385181f2928d328a7aa8c"}'

+ 1 - 1
.env.production

@@ -4,7 +4,7 @@ REACT_APP_BACKEND_V2_POST_URL=https://json.excalidraw.com/api/v2/post/
 REACT_APP_LIBRARY_URL=https://libraries.excalidraw.com
 REACT_APP_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries
 
-REACT_APP_SOCKET_SERVER_URL=https://oss-collab-us1.excalidraw.com
+REACT_APP_PORTAL_URL=https://portal.excalidraw.com
 REACT_APP_FIREBASE_CONFIG='{"apiKey":"AIzaSyAd15pYlMci_xIp9ko6wkEsDzAAA0Dn0RU","authDomain":"excalidraw-room-persistence.firebaseapp.com","databaseURL":"https://excalidraw-room-persistence.firebaseio.com","projectId":"excalidraw-room-persistence","storageBucket":"excalidraw-room-persistence.appspot.com","messagingSenderId":"654800341332","appId":"1:654800341332:web:4a692de832b55bd57ce0c1"}'
 
 # production-only vars

+ 0 - 6
public/index.html

@@ -73,12 +73,6 @@
     />
 
     <link
-      href="%REACT_APP_SOCKET_SERVER_URL%/socket.io"
-      rel="preconnect"
-      crossorigin="anonymous"
-    />
-
-    <link
       rel="manifest"
       href="manifest.json"
       style="--pwacompat-splash-font: 24px Virgil"

+ 17 - 6
src/excalidraw-app/collab/CollabWrapper.tsx

@@ -27,8 +27,8 @@ import {
 import {
   generateCollaborationLinkData,
   getCollaborationLink,
+  getCollabServer,
   SocketUpdateDataSource,
-  SOCKET_SERVER,
 } from "../data";
 import {
   isSavedToFirebase,
@@ -357,11 +357,22 @@ class CollabWrapper extends PureComponent<Props, CollabState> {
       /* webpackChunkName: "socketIoClient" */ "socket.io-client"
     );
 
-    this.portal.socket = this.portal.open(
-      socketIOClient(SOCKET_SERVER),
-      roomId,
-      roomKey,
-    );
+    try {
+      const socketServerData = await getCollabServer();
+      this.portal.socket = this.portal.open(
+        socketIOClient(socketServerData.url, {
+          transports: socketServerData.polling
+            ? ["websocket", "polling"]
+            : ["websocket"],
+        }),
+        roomId,
+        roomKey,
+      );
+    } catch (error: any) {
+      console.error(error);
+      this.setState({ errorMessage: error.message });
+      return null;
+    }
 
     if (!existingRoomLinkData) {
       const elements = this.excalidrawAPI.getSceneElements().map((element) => {

+ 19 - 1
src/excalidraw-app/data/index.ts

@@ -30,7 +30,25 @@ const generateRoomId = async () => {
   return bytesToHexString(buffer);
 };
 
-export const SOCKET_SERVER = process.env.REACT_APP_SOCKET_SERVER_URL;
+/**
+ * Right now the reason why we resolve connection params (url, polling...)
+ * from upstream is to allow changing the params immediately when needed without
+ * having to wait for clients to update the SW.
+ */
+export const getCollabServer = async (): Promise<{
+  url: string;
+  polling: boolean;
+}> => {
+  try {
+    const resp = await fetch(
+      `${process.env.REACT_APP_PORTAL_URL}/collab-server`,
+    );
+    return await resp.json();
+  } catch (error) {
+    console.error(error);
+    throw new Error(t("errors.cannotResolveCollabServer"));
+  }
+};
 
 export type EncryptedData = {
   data: ArrayBuffer;

+ 1 - 1
src/global.d.ts

@@ -21,7 +21,7 @@ declare namespace NodeJS {
   interface ProcessEnv {
     readonly REACT_APP_BACKEND_V2_GET_URL: string;
     readonly REACT_APP_BACKEND_V2_POST_URL: string;
-    readonly REACT_APP_SOCKET_SERVER_URL: string;
+    readonly REACT_APP_PORTAL_URL: string;
     readonly REACT_APP_FIREBASE_CONFIG: string;
   }
 }

+ 2 - 1
src/locales/en.json

@@ -180,7 +180,8 @@
     "imageInsertError": "Couldn't insert image. Try again later...",
     "fileTooBig": "File is too big. Maximum allowed size is {{maxSize}}.",
     "svgImageInsertError": "Couldn't insert SVG image. The SVG markup looks invalid.",
-    "invalidSVGString": "Invalid SVG."
+    "invalidSVGString": "Invalid SVG.",
+    "cannotResolveCollabServer": "Couldn't connect to the collab server. Please reload the page and try again."
   },
   "toolBar": {
     "selection": "Selection",

+ 8 - 0
src/tests/collab.test.tsx

@@ -15,6 +15,14 @@ Object.defineProperty(window, "crypto", {
   },
 });
 
+jest.mock("../excalidraw-app/data/index.ts", () => ({
+  __esmodule: true,
+  ...jest.requireActual("../excalidraw-app/data/index.ts"),
+  getCollabServer: jest.fn(() => ({
+    url: /* doesn't really matter */ "http://localhost:3002",
+  })),
+}));
+
 jest.mock("../excalidraw-app/data/firebase.ts", () => {
   const loadFromFirebase = async () => null;
   const saveToFirebase = () => {};