Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/sync-client/lib/connect-to-project.ts
Views: 687
import Primus from "primus";1import { join } from "path";2import * as responder from "@cocalc/primus-responder";3import * as multiplex from "@cocalc/primus-multiplex";4import type {5ProjectWebsocket,6WebsocketState,7} from "@cocalc/sync/client/types";8import { apiKey, apiServer } from "@cocalc/backend/data";9import versionCookie from "./version-cookie";10import { toCookieHeader } from "./cookies";11import { API_COOKIE_NAME } from "@cocalc/backend/auth/cookie-names";12import basePath from "@cocalc/backend/base-path";13import getLogger from "@cocalc/backend/logger";1415const logger = getLogger("sync-client:connect");16const log = logger.debug;1718export default async function connectToProject(19project_id,20): Promise<ProjectWebsocket> {21if (!apiServer) {22throw Error("API_SERVER must be set");23}24if (!apiKey) {25throw Error("api key must be set (e.g., set API_KEY env variable)");26}27const server = apiServer;28const pathname = join(basePath, project_id, "raw/.smc/ws");29const target = join(server, project_id, "raw/.smc/ws");30log("connectToProject -- ", { pathname, target });31const opts = {32pathname,33transformer: "websockets",34plugin: { responder, multiplex },35} as const;36const Socket = Primus.createSocket(opts);37log("API_COOKIE_NAME = ", API_COOKIE_NAME);38const Cookie = toCookieHeader({39...versionCookie(),40[API_COOKIE_NAME]: apiKey,41});42const socket: ProjectWebsocket = new Socket(server, {43transport: {44// rejectUnauthorized is useful for testing and connecting to a cocalc-docker; it allows connecting to45// server with self-signed cert; obviously a slight risk to allow this.46rejectUnauthorized: false,47headers: { Cookie },48},49// even with this, it seems to take far too long to connect to50// a project, e.g., as compared to the frontend browser.51// I think there is maybe an issue in the proxy server.52reconnect: {53factor: 1.3,54min: 750,55max: 10000,56retries: 10000,57},58}) as any;5960// Every single individual channel creates listeners61// on this socket, and we create several channels per62// document, so we expect a relatively large number63// of listeners on this socket. This is OK, because64// it is rare for events to fire (e.g., it happens when65// the network is down or project restarts).66socket.setMaxListeners(500);6768function updateState(state: WebsocketState) {69if (socket.state == state) {70return; // nothing changed, so no need to set or emit.71}72log("state changed to ", state);73socket.state = state;74socket.emit("state", state);75}7677updateState("offline"); // starts offline7879socket.on("open", () => {80log("open", target);81updateState("online");82});83socket.on("reconnected", () => {84log("reconnected", target);85updateState("online");86});8788socket.on("reconnect", () => {89log("reconnect", target);90updateState("offline");91});92socket.on("reconnect scheduled", () => {93log("reconnect scheduled", target);94updateState("offline");95});9697socket.on("end", () => {98log("end", target);99// maybe todo?100updateState("offline");101});102103return socket;104}105106107