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/project/sync/compute-server-open-file-tracking.ts
Views: 687
/*1Manage the state of open files in the compute servers syncdb sync'd file.23TODO: terminals aren't handled at all here, since they don't have a syncdoc.4*/56import type { SyncDocs } from "./sync-doc";7import type { SyncDB } from "@cocalc/sync/editor/db/sync";8import { once } from "@cocalc/util/async-utils";9import { meta_file, auxFileToOriginal } from "@cocalc/util/misc";10import { terminalTracker } from "@cocalc/terminal";11import { getLogger } from "@cocalc/backend/logger";1213const log = getLogger("project:sync:compute-file-tracker").debug;1415export default async function computeServerOpenFileTracking(16syncDocs: SyncDocs,17compute: SyncDB,18) {19log("initialize");20if (compute.get_state() != "ready") {21log("wait for compute server syncdoc to be ready...");22await once(compute, "ready");23}2425const getOpenPaths = () => {26const v = syncDocs.getOpenPaths().concat(terminalTracker.getOpenPaths());27log("getOpenPaths", v);28return new Set(v);29};30const isOpen = (path: string): boolean => {31return syncDocs.isOpen(path) || terminalTracker.isOpen(path);32};3334// Initialize -- get all open paths and update syncdb state to reflect this correctly.35const openPaths = getOpenPaths();36for (const { path, open } of compute.get().toJS()) {37const syncdocPath = computePathToSyncDocPath(path);38const isOpen = openPaths.has(syncdocPath);39log("init ", { path, open, syncdocPath, isOpen });40if (open != isOpen) {41log("init ", "changing state of ", { path });42compute.set({ path, open: isOpen });43}44}45compute.commit();4647// Watch for files being opened or closed or paths being added/removed from syncdb48const handleOpen = (path: string) => {49log("handleOpen", { path });50if (compute.get_state() == "closed") {51syncDocs.removeListener("open", handleOpen);52return;53}54// A path was opened. If it is in the syncdb, then mark it as opened there.55const x = compute.get_one({ path: syncDocPathToComputePath(path) });56if (x != null) {57compute.set({ path: syncDocPathToComputePath(path), open: true });58compute.commit();59}60};61syncDocs.on("open", handleOpen);62terminalTracker.on("open", handleOpen);6364const handleClose = (path: string) => {65log("handleClose", { path });66if (compute.get_state() == "closed") {67syncDocs.removeListener("open", handleClose);68return;69}70// A path was closed. If it is in the syncdb, then mark it as closed there.71const x = compute.get_one({ path: syncDocPathToComputePath(path) });72if (x != null) {73compute.set({ path: syncDocPathToComputePath(path), open: false });74compute.commit();75}76};7778syncDocs.on("close", handleClose);79// terminals currently don't get closed, but we include this anyways so80// it will "just work" when we do implement that.81terminalTracker.on("close", handleClose);8283// keys is an immutablejs Set of {path} objects84const handleComputeChange = (keys) => {85// The compute server table that tracks where things should run changed.86// If any path was added to that tabl, make sure its open state is correct.87const keyList = keys.toJS();88log("handleComputeChange", { keyList });89let n = 0;90for (const { path } of keyList) {91const x = compute.get_one({ path });92if (x == null) {93// path was REMOVED94log("handleComputeChange: removed", { path });95continue;96}97// path was added or changed in some way -- make sure it agrees98const open = isOpen(computePathToSyncDocPath(path));99if (x.get("open") != open) {100log("handleComputeChange -- making change:", { path, open });101compute.set({ path, open });102n += 1;103}104}105if (n > 0) {106compute.commit();107}108};109110compute.on("change", handleComputeChange);111}112113function syncDocPathToComputePath(path: string): string {114if (path.endsWith(".sage-jupyter2")) {115return auxFileToOriginal(path);116}117return path;118}119120function computePathToSyncDocPath(path: string): string {121if (path.endsWith(".ipynb")) {122return meta_file(path, "jupyter2");123}124return path;125}126127128