Skip to content

Commit 76d388b

Browse files
committed
#286 await websocket fetch
1 parent abf9a11 commit 76d388b

File tree

2 files changed

+46
-10
lines changed

2 files changed

+46
-10
lines changed

lib/src/store.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,9 @@ export class Store {
172172
return `${this.getServerUrl()}/${className}/${random}`;
173173
}
174174

175-
/** Always fetches resource from the server then returns it and adds it to the store */
175+
/**
176+
* Always fetches resource from the server then adds it to the store.
177+
*/
176178
public async fetchResourceFromServer(
177179
/** The resource URL to be fetched */
178180
subject: string,
@@ -198,11 +200,12 @@ export class Store {
198200
const ws = this.getWebSocketForSubject(subject);
199201

200202
if (
203+
!opts.fromProxy &&
201204
!opts.noWebSocket &&
202205
supportsWebSockets() &&
203206
ws?.readyState === WebSocket.OPEN
204207
) {
205-
fetchWebSocket(ws, subject);
208+
await fetchWebSocket(ws, subject);
206209
} else {
207210
const signInfo = this.agent
208211
? { agent: this.agent, serverURL: this.getServerUrl() }

lib/src/websockets.ts

+41-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { createAuthentication } from './authentication.js';
2-
import { JSONADParser, parseAndApplyCommit, Store } from './index.js';
2+
import { JSONADParser, parseAndApplyCommit, Resource, Store } from './index.js';
33

44
/** Opens a Websocket Connection at `/ws` for the current Drive */
55
export function startWebsocket(url: string, store: Store): WebSocket {
@@ -40,11 +40,7 @@ function handleMessage(ev: MessageEvent, store: Store) {
4040
} else if (ev.data.startsWith('ERROR ')) {
4141
store.notifyError(ev.data.slice(6));
4242
} else if (ev.data.startsWith('RESOURCE ')) {
43-
const resourceJSON: string = ev.data.slice(9);
44-
const parsed = JSON.parse(resourceJSON);
45-
const parser = new JSONADParser();
46-
const [_, resources] = parser.parseObject(parsed);
47-
43+
const resources = parseResourceMessage(ev);
4844
store.addResources(...resources);
4945
} else {
5046
console.warn('Unknown websocket message:', ev);
@@ -55,6 +51,15 @@ function handleError(ev: Event) {
5551
console.error('websocket error:', ev);
5652
}
5753

54+
function parseResourceMessage(ev: MessageEvent): Resource[] {
55+
const resourceJSON: string = ev.data.slice(9);
56+
const parsed = JSON.parse(resourceJSON);
57+
const parser = new JSONADParser();
58+
const [_, resources] = parser.parseObject(parsed);
59+
60+
return resources;
61+
}
62+
5863
/**
5964
* Authenticates current Agent over current WebSocket. Doesn't do anything if
6065
* there is no agent
@@ -79,7 +84,35 @@ export async function authenticate(client: WebSocket, store: Store) {
7984
client.send('AUTHENTICATE ' + JSON.stringify(json));
8085
}
8186

87+
const defaultTimeout = 5000;
88+
8289
/** Sends a GET message for some resource over websockets. */
83-
export async function fetchWebSocket(client: WebSocket, subject: string) {
84-
client.send('GET ' + subject);
90+
export async function fetchWebSocket(
91+
client: WebSocket,
92+
subject: string,
93+
): Promise<Resource> {
94+
return new Promise((resolve, reject) => {
95+
client.addEventListener('message', function listener(ev) {
96+
const timeoutId = setTimeout(() => {
97+
client.removeEventListener('message', listener);
98+
reject(
99+
new Error(
100+
`Request for subject "${subject}" timed out after ${defaultTimeout}ms.`,
101+
),
102+
);
103+
}, defaultTimeout);
104+
105+
if (ev.data.startsWith('RESOURCE ')) {
106+
parseResourceMessage(ev).forEach(resource => {
107+
// if it is the requested subject, return the resource
108+
if (resource.getSubject() === subject) {
109+
clearTimeout(timeoutId);
110+
client.removeEventListener('message', listener);
111+
resolve(resource);
112+
}
113+
});
114+
}
115+
});
116+
client.send('GET ' + subject);
117+
});
85118
}

0 commit comments

Comments
 (0)