CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/project/sync/project-info.ts
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { reuseInFlight } from "@cocalc/util/reuse-in-flight";
7
import { close } from "@cocalc/util/misc";
8
import { SyncTable } from "@cocalc/sync/table";
9
import { get_ProjectInfoServer } from "../project-info";
10
import { ProjectInfo } from "@cocalc/util/types/project-info/types";
11
import { ProjectInfoServer } from "../project-info";
12
13
class ProjectInfoTable {
14
private table: SyncTable;
15
private logger: { debug: Function };
16
private project_id: string;
17
private state: "ready" | "closed" = "ready";
18
private readonly publish: (info: ProjectInfo) => Promise<void>;
19
private readonly info_server: ProjectInfoServer;
20
21
constructor(
22
table: SyncTable,
23
logger: { debug: Function },
24
project_id: string
25
) {
26
this.project_id = project_id;
27
this.logger = logger;
28
this.log("register");
29
this.publish = reuseInFlight(this.publish_impl.bind(this));
30
this.table = table;
31
this.table.on("closed", () => this.close());
32
// initializing project info server + reacting when it has something to say
33
this.info_server = get_ProjectInfoServer();
34
this.info_server.start();
35
this.info_server.on("info", this.publish);
36
}
37
38
private async publish_impl(info: ProjectInfo): Promise<void> {
39
if (this.state == "ready" && this.table.get_state() != "closed") {
40
const next = { project_id: this.project_id, info };
41
this.table.set(next, "shallow");
42
try {
43
await this.table.save();
44
} catch (err) {
45
this.log(`error saving ${err}`);
46
}
47
} else if (this.log != null) {
48
this.log(
49
`ProjectInfoTable state = '${
50
this.state
51
}' and table is '${this.table?.get_state()}'`
52
);
53
}
54
}
55
56
public close(): void {
57
this.log("close");
58
this.info_server?.off("info", this.publish);
59
this.table?.close_no_async();
60
close(this);
61
this.state = "closed";
62
}
63
64
private log(...args): void {
65
if (this.logger == null) return;
66
this.logger.debug("project_info", ...args);
67
}
68
}
69
70
let project_info_table: ProjectInfoTable | undefined = undefined;
71
72
export function register_project_info_table(
73
table: SyncTable,
74
logger: any,
75
project_id: string
76
): void {
77
logger.debug("register_project_info_table");
78
if (project_info_table != null) {
79
logger.debug(
80
"register_project_info_table: cleaning up an already existing one"
81
);
82
project_info_table.close();
83
}
84
project_info_table = new ProjectInfoTable(table, logger, project_id);
85
}
86
87
export function get_project_info_table(): ProjectInfoTable | undefined {
88
return project_info_table;
89
}
90
91