import debug from "debug";
import { parseJsonPatch, Patch, patchSizeSummary, toJsonPatch } from "./patch";
import { RdfDbChannel } from "./RdfDbChannel";
export const log = debug("rdfdbclient");
export class RdfDbClient {
private channel: RdfDbChannel;
_patchesToSend: Patch[];
// Send and receive patches from rdfdb. Primarily used in SyncedGraph.
//
// What this should do, and does not yet, is keep the graph
// 'coasting' over a reconnect, applying only the diffs from the old
// contents to the new ones once they're in. Then, remove all the
// clearGraph stuff in graph.coffee that doesn't even work right.
//
constructor(
patchSenderUrl: string,
private clearGraphOnNewConnection: () => void,
private applyPatch: (p: Patch) => void,
setStatus: (status: string) => void
) {
this._patchesToSend = [];
this.channel = new RdfDbChannel(patchSenderUrl);
this.channel.statusDisplay.subscribe((st: string) => {
setStatus(st + `; ${this._patchesToSend.length} pending `);
});
this.channel.newConnection.subscribe(() => {
this.clearGraphOnNewConnection();
});
this.channel.serverMessage.subscribe((m) => {
parseJsonPatch(m.body, this.applyPatch.bind(this));
});
}
sendPatch(patch: Patch) {
log("queue patch to server ", patchSizeSummary(patch));
this._patchesToSend.push(patch);
this._continueSending();
}
disconnect() {
this.channel.disconnect();
}
async _continueSending() {
// we could call this less often and coalesce patches together to optimize
// the dragging cases.
while (this._patchesToSend.length) {
const patch = this._patchesToSend.splice(0, 1)[0];
const json = await new Promise<string>((res, rej) => {
toJsonPatch(patch, res);
});
const ret = this.channel.sendMessage(json);
if (!ret) {
setTimeout(this._continueSending.bind(this), 500);
// this.disconnect()
return;
}
}
}
}