@cocalc/project
Version:
CoCalc: project daemon
90 lines (80 loc) • 2.69 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_ProjectInfoServer } from "../project-info";
import { ProjectInfo } from "../project-info/types";
import { ProjectInfoServer } from "../project-info";
class ProjectInfoTable {
private table: SyncTable;
private logger: { debug: Function };
private project_id: string;
private state: "ready" | "closed" = "ready";
private readonly publish: (info: ProjectInfo) => Promise<void>;
private readonly info_server: ProjectInfoServer;
constructor(
table: SyncTable,
logger: { debug: Function },
project_id: string
) {
this.project_id = project_id;
this.logger = logger;
this.log("register");
this.publish = reuseInFlight(this.publish_impl.bind(this));
this.table = table;
this.table.on("closed", () => this.close());
// initializing project info server + reacting when it has something to say
this.info_server = get_ProjectInfoServer();
this.info_server.start();
this.info_server.on("info", this.publish);
}
private async publish_impl(info: ProjectInfo): Promise<void> {
if (this.state == "ready" && this.table.get_state() != "closed") {
const next = { project_id: this.project_id, info };
this.table.set(next, "shallow");
try {
await this.table.save();
} catch (err) {
this.log(`error saving ${err}`);
}
} else if (this.log != null) {
this.log(
`ProjectInfoTable state = '${
this.state
}' and table is '${this.table?.get_state()}'`
);
}
}
public close(): void {
this.log("close");
this.info_server?.off("info", this.publish);
this.table?.close_no_async();
close(this);
this.state = "closed";
}
private log(...args): void {
if (this.logger == null) return;
this.logger.debug("project_info", ...args);
}
}
let project_info_table: ProjectInfoTable | undefined = undefined;
export function register_project_info_table(
table: SyncTable,
logger: any,
project_id: string
): void {
logger.debug("register_project_info_table");
if (project_info_table != null) {
logger.debug(
"register_project_info_table: cleaning up an already existing one"
);
project_info_table.close();
}
project_info_table = new ProjectInfoTable(table, logger, project_id);
}
export function get_project_info_table(): ProjectInfoTable | undefined {
return project_info_table;
}