@cocalc/project
Version:
CoCalc: project daemon
104 lines (86 loc) • 2.45 kB
text/typescript
/*
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
* License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
*/
/*
Channels used for maybe nothing right now.
I thought this would be useful, but it hasn't yet turned out to be.
*/
import { EventEmitter } from "events";
const sync_tables = {};
function get_name(name: string): string {
return `symmetric_channel:${name}`;
}
export async function browser_symmetric_channel(
_: any,
primus: any,
logger: any,
name: string
): Promise<string> {
name = get_name(name);
// The code below is way more complicated because SymmetricChannel
// can be made *before* this sync function is called. If that
// happens, and we also have to set the channel of SymmetricChannel.
if (
sync_tables[name] !== undefined &&
sync_tables[name].channel !== undefined
) {
// fully initialized
return name;
}
const channel = primus.channel(name);
let local: SymmetricChannel;
if (sync_tables[name] !== undefined) {
local = sync_tables[name].local;
local.channel = channel;
sync_tables[name].channel = channel;
} else {
local = new SymmetricChannel(channel);
sync_tables[name] = {
local,
channel,
};
}
channel.on("connection", function (spark: any): void {
// Now handle a connection
logger.debug("sync", name, `conn from ${spark.address.ip} -- ${spark.id}`);
spark.on("end", function () {
logger.debug("sync", name, `closed ${spark.address.ip} -- ${spark.id}`);
});
spark.on("data", function (data) {
local._data_from_spark(data);
channel.forEach(function (spark0, id) {
if (id !== spark.id) {
spark0.write(data);
}
});
});
});
return name;
}
class SymmetricChannel extends EventEmitter {
channel: any;
constructor(channel?: any) {
super();
this.channel = channel;
}
// Returns true if immediate write succeeds
write(data: any): boolean {
if (this.channel !== undefined) {
return this.channel.write(data);
}
return false;
}
_data_from_spark(data: any): void {
this.emit("data", data);
}
}
export function symmetric_channel(name: string): SymmetricChannel {
name = get_name(name);
if (sync_tables[name] !== undefined) {
return sync_tables[name].local;
}
const local = new SymmetricChannel(undefined);
sync_tables[name] = { local };
return local;
}