@cocalc/project
Version:
CoCalc: project daemon
91 lines (81 loc) • 2.32 kB
text/typescript
/*
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
* License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
*/
/*
All SyncTables that are currently open and being managed in this project.
*/
import { callback } from "awaiting";
import { SyncTable } from "@cocalc/sync/table";
import { is_array } from "@cocalc/util/misc";
const open_synctables: { [key: string]: SyncTable } = {};
const wait_for: { [key: string]: Function[] } = {};
export function key(query): string {
const table: string = Object.keys(query)[0];
if (!table) {
throw Error("no table in query");
}
let c = query[table];
if (c == null) {
throw Error("invalid query format");
}
if (is_array(c)) {
c = c[0];
}
const string_id = c.string_id;
if (string_id == null) {
throw Error(
"open-syncstring-tables is only for queries with a specified string_id field" +
"(patches, cursors, eval_inputs, eval_outputs, etc.): query=" +
JSON.stringify(query)
);
}
return `${table}.${string_id}`;
}
export function register_synctable(query: any, synctable: SyncTable): void {
const k = key(query);
open_synctables[k] = synctable;
synctable.on("closed", function () {
delete open_synctables[k];
});
if (wait_for[k] != null) {
handle_wait_for(k, synctable);
}
}
export async function get_synctable(query, client): Promise<SyncTable> {
const k = key(query);
const log = client.dbg(`get_synctable(key=${k})`);
log("open_synctables = ", Object.keys(open_synctables));
log("key=", k, "query=", query);
const s = open_synctables[k];
if (s != null) {
// easy - already have it.
log("done");
return s;
}
function f(cb: Function) {
log("f got called");
add_to_wait_for(k, cb);
}
log("waiting...");
const synctable = await callback(f);
log(`got the synctable! ${JSON.stringify((synctable as any).query)}`);
return synctable;
}
function add_to_wait_for(k: string, cb: Function): void {
if (wait_for[k] == null) {
wait_for[k] = [cb];
} else {
wait_for[k].push(cb);
}
}
function handle_wait_for(k: string, synctable: SyncTable): void {
if (wait_for[k] == null) {
return;
}
const v: Function[] = wait_for[k];
delete wait_for[k];
for (const cb of v) {
cb(undefined, synctable);
}
}