@cocalc/project
Version:
CoCalc: project daemon
98 lines (87 loc) • 2.92 kB
text/typescript
/*
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
* License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
*/
import { reuseInFlight } from "async-await-utils/hof";
import { close } from "@cocalc/util/misc";
import { SyncTable } from "@cocalc/sync/table";
import {
get_ProjectStatusServer,
ProjectStatusServer,
} from "../project-status";
import { ProjectStatus } from "../project-status/types";
class ProjectStatusTable {
private table: SyncTable;
private logger: { debug: Function };
private project_id: string;
private state: "ready" | "closed" = "ready";
private readonly publish: (status: ProjectStatus) => Promise<void>;
private readonly status_server: ProjectStatusServer;
constructor(
table: SyncTable,
logger: { debug: Function },
project_id: string
) {
this.status_handler = this.status_handler.bind(this);
this.project_id = project_id;
this.logger = logger;
this.log("register");
this.publish = reuseInFlight(this.publish_impl);
this.table = table;
this.table.on("closed", () => this.close());
// initializing project status server + reacting when it has something to say
this.status_server = get_ProjectStatusServer();
this.status_server.start();
this.status_server.on("status", this.status_handler);
}
private status_handler(status): void {
this.log?.("status_server event 'status'", status.timestamp);
this.publish?.(status);
}
private async publish_impl(status: ProjectStatus): Promise<void> {
if (this.state == "ready" && this.table.get_state() != "closed") {
const next = { project_id: this.project_id, status };
this.table.set(next, "shallow");
try {
await this.table.save();
} catch (err) {
this.log(`error saving ${err}`);
}
} else if (this.log != null) {
this.log(
`ProjectStatusTable '${
this.state
}' and table is ${this.table?.get_state()}`
);
}
}
public close(): void {
this.log("close");
this.status_server?.off("status", this.status_handler);
this.table?.close_no_async();
close(this);
this.state = "closed";
}
private log(...args): void {
if (this.logger == null) return;
this.logger.debug("project_status", ...args);
}
}
let project_status_table: ProjectStatusTable | undefined = undefined;
export function register_project_status_table(
table: SyncTable,
logger: any,
project_id: string
): void {
logger.debug("register_project_status_table");
if (project_status_table != null) {
logger.debug(
"register_project_status_table: cleaning up an already existing one"
);
project_status_table.close();
}
project_status_table = new ProjectStatusTable(table, logger, project_id);
}
export function get_project_status_table(): ProjectStatusTable | undefined {
return project_status_table;
}