115 lines
3.0 KiB
TypeScript
Raw Normal View History

2023-11-07 00:50:47 +01:00
import { PUBSUB_TOPIC } from "@/constants";
2023-11-01 01:52:51 +01:00
import { http } from "@/utils/http";
2023-10-30 23:57:10 +01:00
2023-11-01 01:52:51 +01:00
export type Message = {
2023-11-07 00:50:47 +01:00
payload: string;
contentTopic: string;
version: number;
timestamp: number;
2023-10-30 23:57:10 +01:00
};
2023-11-01 01:52:51 +01:00
type EventListener = (event: CustomEvent) => void;
2023-10-30 23:57:10 +01:00
2023-11-01 01:52:51 +01:00
const SECOND = 1000;
const LOCAL_NODE = "http://127.0.0.1:8645/";
2023-11-07 00:50:47 +01:00
const RELAY = "/relay/v1";
2023-10-30 23:57:10 +01:00
2023-11-07 00:50:47 +01:00
const buildURL = (endpoint: string) => `${LOCAL_NODE}${endpoint}`;
class Relay {
2023-11-01 01:52:51 +01:00
private readonly subscriptionsEmitter = new EventTarget();
2023-10-30 23:57:10 +01:00
2023-11-01 01:52:51 +01:00
private contentTopicListeners: Map<string, number> = new Map();
2023-10-30 23:57:10 +01:00
2023-11-01 01:52:51 +01:00
// only one content topic subscriptions is possible now
private subscriptionRoutine: undefined | number;
2023-10-30 23:57:10 +01:00
2023-11-07 00:50:47 +01:00
constructor() {}
public addEventListener(contentTopic: string, fn: EventListener) {
this.handleSubscribed(contentTopic);
return this.subscriptionsEmitter.addEventListener(contentTopic, fn as any);
}
public removeEventListener(contentTopic: string, fn: EventListener) {
this.handleUnsubscribed(contentTopic);
return this.subscriptionsEmitter.removeEventListener(
contentTopic,
fn as any
);
2023-11-01 01:52:51 +01:00
}
2023-11-07 00:50:47 +01:00
private async handleSubscribed(contentTopic: string) {
const numberOfListeners = this.contentTopicListeners.get(contentTopic);
// if nwaku node already subscribed to this content topic
if (numberOfListeners) {
this.contentTopicListeners.set(contentTopic, numberOfListeners + 1);
return;
}
try {
await http.post(buildURL(`${RELAY}/subscriptions`), [PUBSUB_TOPIC]);
2023-10-30 23:57:10 +01:00
2023-11-01 01:52:51 +01:00
this.subscriptionRoutine = window.setInterval(async () => {
await this.fetchMessages();
}, SECOND);
2023-10-30 23:57:10 +01:00
2023-11-01 01:52:51 +01:00
this.contentTopicListeners.set(contentTopic, 1);
2023-11-07 00:50:47 +01:00
} catch (error) {
console.error(`Failed to subscribe node ${contentTopic}:`, error);
}
2023-11-01 01:52:51 +01:00
}
2023-10-30 23:57:10 +01:00
2023-11-07 00:50:47 +01:00
private async handleUnsubscribed(contentTopic: string) {
2023-11-01 01:52:51 +01:00
const numberOfListeners = this.contentTopicListeners.get(contentTopic);
2023-10-30 23:57:10 +01:00
2023-11-07 00:50:47 +01:00
if (!numberOfListeners) {
2023-10-30 23:57:10 +01:00
return;
}
2023-11-01 01:52:51 +01:00
if (numberOfListeners - 1 > 0) {
this.contentTopicListeners.set(contentTopic, numberOfListeners - 1);
return;
2023-10-30 23:57:10 +01:00
}
2023-11-07 00:50:47 +01:00
try {
await http.delete(buildURL(`${RELAY}/subscriptions`), [PUBSUB_TOPIC]);
} catch (error) {
console.error(`Failed to unsubscribe node from ${contentTopic}:`, error);
}
2023-11-01 01:52:51 +01:00
clearInterval(this.subscriptionRoutine);
this.contentTopicListeners.delete(contentTopic);
2023-10-30 23:57:10 +01:00
}
2023-11-01 01:52:51 +01:00
private async fetchMessages(): Promise<void> {
const contentTopic = Object.keys(this.contentTopicListeners)[0];
if (!contentTopic) {
2023-10-30 23:57:10 +01:00
return;
}
2023-11-07 00:50:47 +01:00
const response = await http.get(
buildURL(`${RELAY}/messages/${encodeURIComponent(PUBSUB_TOPIC)}`)
);
2023-11-01 01:52:51 +01:00
const body: Message[] = await response.json();
2023-10-30 23:57:10 +01:00
2023-11-01 01:52:51 +01:00
if (!body || !body.length) {
2023-10-30 23:57:10 +01:00
return;
}
2023-11-01 01:52:51 +01:00
this.subscriptionsEmitter.dispatchEvent(
new CustomEvent(contentTopic, { detail: body })
);
2023-10-30 23:57:10 +01:00
}
2023-11-01 01:52:51 +01:00
public async send(message: Message): Promise<void> {
2023-11-07 00:50:47 +01:00
await http.post(buildURL(`${RELAY}/messages/${encodeURIComponent(PUBSUB_TOPIC)}`), message);
2023-10-30 23:57:10 +01:00
}
}
2023-11-01 01:52:51 +01:00
export const waku = {
2023-11-07 00:50:47 +01:00
relay: new Relay(),
};