annotate web/RdfDbChannel.ts @ 2405:69ca2b2fc133

overcomplicated attempt at persisting the pane layout in the rdf graph this was hard because we have to somehow wait for the graph to load before config'ing the panes
author drewp@bigasterisk.com
date Fri, 17 May 2024 16:58:26 -0700
parents 4556eebe5d73
children ac55319a2eac
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2256
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
1 import debug from "debug";
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
2 import { SubEvent } from "sub-events";
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
3 import { SyncgraphPatchMessage } from "./patch";
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
4 const log = debug("rdfdbclient");
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
5
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
6 class ChannelPinger {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
7 private timeoutId?: number;
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
8 private lastMs: number = 0;
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
9 constructor(private ws: WebSocket) {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
10 this._pingLoop();
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
11 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
12 lastPingMs(): number {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
13 return this.lastMs;
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
14 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
15 pong() {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
16 this.lastMs = Date.now() + this.lastMs;
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
17 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
18 _pingLoop() {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
19 if (this.ws.readyState !== this.ws.OPEN) {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
20 return;
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
21 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
22 this.ws.send("PING");
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
23 this.lastMs = -Date.now();
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
24
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
25 if (this.timeoutId != null) {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
26 clearTimeout(this.timeoutId);
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
27 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
28 this.timeoutId = (setTimeout(this._pingLoop.bind(this), 10000) as unknown) as number;
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
29 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
30 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
31
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
32 export class RdfDbChannel {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
33 // lower level reconnecting websocket -- knows about message types, but not what's inside a patch body
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
34 private ws?: WebSocket = undefined;
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
35 private pinger?: ChannelPinger;
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
36 private connectionId: string = "none"; // server's name for us
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
37 private reconnectTimer?: NodeJS.Timeout = undefined;
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
38 private messagesReceived = 0; // (non-ping messages)
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
39 private messagesSent = 0;
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
40
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
41 newConnection: SubEvent<void> = new SubEvent();
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
42 serverMessage: SubEvent<{ evType: string; body: SyncgraphPatchMessage }> = new SubEvent();
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
43 statusDisplay: SubEvent<string> = new SubEvent();
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
44
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
45 constructor(public patchSenderUrl: string) {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
46 this.openConnection();
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
47 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
48 sendMessage(body: string): boolean {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
49 // one try, best effort, true if we think it worked
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
50 if (!this.ws || this.ws.readyState !== this.ws.OPEN) {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
51 return false;
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
52 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
53 log("send patch to server, " + body.length + " bytes");
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
54 this.ws.send(body);
2289
f2c6b39c155c fix messagesSend counter
drewp@bigasterisk.com
parents: 2285
diff changeset
55 this.messagesSent++;
f2c6b39c155c fix messagesSend counter
drewp@bigasterisk.com
parents: 2285
diff changeset
56 this.updateStatus();
2256
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
57 return true;
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
58 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
59
2322
cdfd2901918a logging
drewp@bigasterisk.com
parents: 2289
diff changeset
60 disconnect(why:string) {
2256
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
61 // will be followed by an autoconnect
2322
cdfd2901918a logging
drewp@bigasterisk.com
parents: 2289
diff changeset
62 log("disconnect requested:", why);
2256
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
63 if (this.ws !== undefined) {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
64 const closeHandler = this.ws.onclose?.bind(this.ws);
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
65 if (!closeHandler) {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
66 throw new Error();
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
67 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
68 closeHandler(new CloseEvent("forced"));
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
69 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
70 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
71
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
72 private openConnection() {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
73 const wsOrWss = window.location.protocol.replace("http", "ws");
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
74 const fullUrl = wsOrWss + "//" + window.location.host + this.patchSenderUrl;
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
75 if (this.ws !== undefined) {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
76 this.ws.close();
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
77 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
78 this.ws = new WebSocket(fullUrl);
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
79 this.ws.onopen = this.onWsOpen.bind(this, this.ws);
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
80 this.ws.onerror = this.onWsError.bind(this);
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
81 this.ws.onclose = this.onWsClose.bind(this);
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
82 this.ws.onmessage = this.onWsMessage.bind(this);
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
83 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
84
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
85 private onWsOpen(ws: WebSocket) {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
86 log("new connection to", this.patchSenderUrl);
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
87 this.updateStatus();
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
88 this.newConnection.emit();
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
89 this.pinger = new ChannelPinger(ws);
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
90 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
91
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
92 private onWsMessage(evt: { data: string }) {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
93 const msg = evt.data;
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
94 if (msg === "PONG") {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
95 this.onPong();
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
96 return;
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
97 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
98 this.onJson(msg);
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
99 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
100
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
101 private onPong() {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
102 if (this.pinger) {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
103 this.pinger.pong();
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
104 this.updateStatus();
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
105 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
106 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
107
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
108 private onJson(msg: string) {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
109 const input = JSON.parse(msg);
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
110 if (input.connectedAs) {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
111 this.connectionId = input.connectedAs;
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
112 } else {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
113 this.onPatch(input as SyncgraphPatchMessage);
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
114 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
115 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
116
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
117 private onPatch(input: SyncgraphPatchMessage) {
2285
cc371473ada1 logging
drewp@bigasterisk.com
parents: 2256
diff changeset
118 log(`patch msg from server`);
2256
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
119 this.serverMessage.emit({ evType: "patch", body: input });
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
120 this.messagesReceived++;
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
121 this.updateStatus();
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
122 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
123
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
124 private onWsError(e: Event) {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
125 log("ws error", e);
2322
cdfd2901918a logging
drewp@bigasterisk.com
parents: 2289
diff changeset
126 this.disconnect("ws error");
2256
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
127 this.updateStatus();
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
128 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
129
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
130 private onWsClose(ev: CloseEvent) {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
131 log("ws close");
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
132 this.updateStatus();
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
133 if (this.reconnectTimer !== undefined) {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
134 clearTimeout(this.reconnectTimer);
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
135 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
136 this.reconnectTimer = setTimeout(this.openConnection.bind(this), 1000);
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
137 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
138
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
139 private updateStatus() {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
140 const conn = (() => {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
141 if (this.ws === undefined) {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
142 return "no";
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
143 } else {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
144 switch (this.ws.readyState) {
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
145 case this.ws.CONNECTING:
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
146 return "connecting";
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
147 case this.ws.OPEN:
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
148 return `open as ${this.connectionId}`;
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
149 case this.ws.CLOSING:
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
150 return "closing";
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
151 case this.ws.CLOSED:
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
152 return "close";
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
153 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
154 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
155 })();
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
156
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
157 const ping = this.pinger ? this.pinger.lastPingMs() : "...";
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
158 this.statusDisplay.emit(`${conn}; ${this.messagesReceived} recv; ${this.messagesSent} sent; ping ${ping}ms`);
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
159 }
eb34653d315d move to RdfDbChannel.ts
drewp@bigasterisk.com
parents:
diff changeset
160 }