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-status.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 {
10
get_ProjectStatusServer,
11
ProjectStatusServer,
12
} from "../project-status";
13
import { ProjectStatus } from "@cocalc/comm/project-status/types";
14
15
class ProjectStatusTable {
16
private table: SyncTable;
17
private logger: { debug: Function };
18
private project_id: string;
19
private state: "ready" | "closed" = "ready";
20
private readonly publish: (status: ProjectStatus) => Promise<void>;
21
private readonly status_server: ProjectStatusServer;
22
23
constructor(
24
table: SyncTable,
25
logger: { debug: Function },
26
project_id: string,
27
) {
28
this.status_handler = this.status_handler.bind(this);
29
this.project_id = project_id;
30
this.logger = logger;
31
this.log("register");
32
this.publish = reuseInFlight(this.publish_impl.bind(this));
33
this.table = table;
34
this.table.on("closed", () => this.close());
35
// initializing project status server + reacting when it has something to say
36
this.status_server = get_ProjectStatusServer();
37
this.status_server.start();
38
this.status_server.on("status", this.status_handler);
39
}
40
41
private status_handler(status): void {
42
this.log?.("status_server event 'status'", status.timestamp);
43
this.publish?.(status);
44
}
45
46
private async publish_impl(status: ProjectStatus): Promise<void> {
47
if (this.state == "ready" && this.table.get_state() != "closed") {
48
const next = { project_id: this.project_id, status };
49
this.table.set(next, "shallow");
50
try {
51
await this.table.save();
52
} catch (err) {
53
this.log(`error saving ${err}`);
54
}
55
} else if (this.log != null) {
56
this.log(
57
`ProjectStatusTable '${
58
this.state
59
}' and table is ${this.table?.get_state()}`,
60
);
61
}
62
}
63
64
public close(): void {
65
this.log("close");
66
this.status_server?.off("status", this.status_handler);
67
this.table?.close_no_async();
68
close(this);
69
this.state = "closed";
70
}
71
72
private log(...args): void {
73
if (this.logger == null) return;
74
this.logger.debug("project_status", ...args);
75
}
76
}
77
78
let project_status_table: ProjectStatusTable | undefined = undefined;
79
80
export function register_project_status_table(
81
table: SyncTable,
82
logger: any,
83
project_id: string,
84
): void {
85
logger.debug("register_project_status_table");
86
if (project_status_table != null) {
87
logger.debug(
88
"register_project_status_table: cleaning up an already existing one",
89
);
90
project_status_table.close();
91
}
92
project_status_table = new ProjectStatusTable(table, logger, project_id);
93
}
94
95
export function get_project_status_table(): ProjectStatusTable | undefined {
96
return project_status_table;
97
}
98
99