From 66660729732724ef5b4afb7d0e2fbba6c419ded8 Mon Sep 17 00:00:00 2001 From: Franz Geffke Date: Tue, 5 Sep 2023 11:38:16 +0100 Subject: [PATCH] client-web: improve performance; fix view subscription; up limit to 150 --- client-web/package.json | 2 +- .../src/components/user-profile-form.tsx | 1 + client-web/src/defaults.ts | 2 +- client-web/src/routes/user-profile.tsx | 1 + client-web/src/state/client.ts | 85 +++++-------------- client-web/src/state/worker-types.ts | 3 + client-web/src/state/worker.ts | 54 +++++++++++- packages/common/src/classes/relay-client.ts | 4 + 8 files changed, 83 insertions(+), 69 deletions(-) diff --git a/client-web/package.json b/client-web/package.json index 0fbe4a2..82a0298 100644 --- a/client-web/package.json +++ b/client-web/package.json @@ -1,7 +1,7 @@ { "name": "client-web", "version": "0.0.4", - "description": "Nostr react playground", + "description": "Nostr react client", "author": "Franz Geffke ", "license": "MIT", "type": "module", diff --git a/client-web/src/components/user-profile-form.tsx b/client-web/src/components/user-profile-form.tsx index 3231f93..a496a7e 100644 --- a/client-web/src/components/user-profile-form.tsx +++ b/client-web/src/components/user-profile-form.tsx @@ -86,6 +86,7 @@ export function UserProfileForm({ props }: { props: UserProfileFormProps }) { }), options: { timeoutIn: 10000, + view: "user-profile", }, }); } catch (e) { diff --git a/client-web/src/defaults.ts b/client-web/src/defaults.ts index 49bfa5b..be996b5 100644 --- a/client-web/src/defaults.ts +++ b/client-web/src/defaults.ts @@ -1,4 +1,4 @@ -export const MAX_EVENTS = 50; +export const MAX_EVENTS = 150; export const DEFAULT_RELAYS = { "wss://relay.shitforce.one": { read: true, diff --git a/client-web/src/routes/user-profile.tsx b/client-web/src/routes/user-profile.tsx index 1c6a2e1..2d81fbb 100644 --- a/client-web/src/routes/user-profile.tsx +++ b/client-web/src/routes/user-profile.tsx @@ -49,6 +49,7 @@ export function UserProfileRoute() { }), options: { timeoutIn: 10000, + view: "user-profile", }, }); toast({ diff --git a/client-web/src/state/client.ts b/client-web/src/state/client.ts index c21ecd0..b1a5f8a 100644 --- a/client-web/src/state/client.ts +++ b/client-web/src/state/client.ts @@ -11,7 +11,6 @@ import { CountRequest, PublishingRequest, WebSocketClientInfo, - CLIENT_MESSAGE_TYPE, RelaysWithIdsOrKeys, AuthRequest, CloseRequest, @@ -96,7 +95,7 @@ export const useNClient = create((set, get) => ({ }); }; - const throttledEvents = throttle(processEvents, 100); + const throttledEvents = throttle(processEvents, 500); worker.addEventListener("message", throttledEvents); const following = await get().store.getAllUsersFollowing(); @@ -234,15 +233,14 @@ export const useNClient = create((set, get) => ({ }); }, updateEvent: (payload: ProcessedEvent) => { - const eventIndex = get().events.findIndex( - (event) => event.event.id === payload.event.id - ); - - if (eventIndex !== -1) { - const updatedEvents = [...get().events]; - updatedEvents[eventIndex] = payload; - set({ events: updatedEvents }); - } + set({ + events: get().events.map((event) => { + if (event.event.id === payload.event.id) { + return payload; + } + return event; + }), + }); }, maxEvents: MAX_EVENTS, setMaxEvents: async (max: number) => { @@ -319,13 +317,14 @@ export const useNClient = create((set, get) => ({ }); }, updateQueueItem: async (item: PublishingQueueItem) => { - const queue = get().eventsPublishingQueue; - const index = queue.findIndex((e) => e.event.id === item.event.id); - if (index !== -1) { - const updatedQueue = [...queue]; - updatedQueue[index] = item; - set({ eventsPublishingQueue: updatedQueue }); - } + set({ + eventsPublishingQueue: get().eventsPublishingQueue.map((e) => { + if (e.id === item.id) { + return item; + } + return e; + }), + }); }, getUser: async (pubkey: string) => { return get().store.getUser(pubkey); @@ -545,43 +544,7 @@ export const useNClient = create((set, get) => ({ * @returns */ setViewSubscription: async (view: string, filters: NFilters) => { - const subs = await get().getSubscriptions(); - const subIds = []; - for (const sub of subs) { - if (sub.options && sub.options.view) { - subIds.push(sub.id); - } - } - if (subIds.length > 0) { - await get().unsubscribe(subIds); - } - - const relays = await get().getRelays(); - - await get().subscribe({ - type: CLIENT_MESSAGE_TYPE.REQ, - filters: { - ...filters, - limit: filters.limit - ? Math.round(filters.limit / relays.length) - : undefined, - }, - options: { - view, - timeoutIn: 15000, - }, - }); - - // TODO: This is not accurate - setTimeout(async () => { - await get().store.processActiveEvents(view); - }, 1500); - setTimeout(async () => { - await get().store.processActiveEvents(view); - }, 6000); - setTimeout(async () => { - await get().store.processActiveEvents(view); - }, 12000); + await get().store.setViewSubscription(view, filters); }, /** @@ -590,16 +553,6 @@ export const useNClient = create((set, get) => ({ * @returns */ removeViewSubscription: async (view: string) => { - const subs = await get().getSubscriptions(); - - console.log(`Remove view subscription ${view}`); - - const filteredSubs = subs.filter( - (sub) => sub.options && sub.options.view === view - ); - - if (filteredSubs.length === 0) { - await get().unsubscribe(filteredSubs.map((sub) => sub.id)); - } + await get().store.removeViewSubscription(view); }, })); diff --git a/client-web/src/state/worker-types.ts b/client-web/src/state/worker-types.ts index 49b18c8..bfcb14f 100644 --- a/client-web/src/state/worker-types.ts +++ b/client-web/src/state/worker-types.ts @@ -6,6 +6,7 @@ import { PublishingQueueItem, CountRequest, RelaySubscription, + NFilters, } from "@nostr-ts/common"; import { NClientBase } from "./base-types"; @@ -34,6 +35,8 @@ export interface NClientWorker extends NClientBase { } ) => void; + setViewSubscription: (view: string, filters: NFilters) => void; + removeViewSubscription: (view: string) => void; processActiveEvents: (view: string) => void; /** diff --git a/client-web/src/state/worker.ts b/client-web/src/state/worker.ts index a6f5361..1f98a19 100644 --- a/client-web/src/state/worker.ts +++ b/client-web/src/state/worker.ts @@ -727,7 +727,6 @@ class WorkerClass implements NClientWorker { } clearEvents() { - console.log(`WORKER: CLEAR EVENTS`); incomingQueue.clearPriority(); this.eventsMap.clear(); this.checkedEvents = []; @@ -819,6 +818,59 @@ class WorkerClass implements NClientWorker { } } + async setViewSubscription(view: string, filters: NFilters) { + const subs = this.getSubscriptions(); + const subIds = []; + for (const sub of subs) { + if (sub.options && sub.options.view) { + subIds.push(sub.id); + } + } + if (subIds.length > 0) { + this.unsubscribe(subIds); + } + + const relays = this.getRelays(); + + await this.subscribe({ + type: CLIENT_MESSAGE_TYPE.REQ, + filters: { + ...filters, + limit: filters.limit + ? Math.round(filters.limit / relays.length) + : undefined, + }, + options: { + view, + timeoutIn: 15000, + }, + }); + + // TODO: This is not accurate + setTimeout(async () => { + await this.processActiveEvents(view); + }, 1500); + setTimeout(async () => { + await this.processActiveEvents(view); + }, 6000); + setTimeout(async () => { + await this.processActiveEvents(view); + }, 12000); + } + + removeViewSubscription(view: string) { + const subs = this.getSubscriptions(); + const subIds = []; + for (const sub of subs) { + if (sub.options && sub.options.view === view) { + subIds.push(sub.id); + } + } + if (subIds.length > 0) { + this.unsubscribe(subIds); + } + } + async processActiveEvents(view: string) { const eventUserPubkeys: { pubkey: string; diff --git a/packages/common/src/classes/relay-client.ts b/packages/common/src/classes/relay-client.ts index 72dcb93..f071fe3 100644 --- a/packages/common/src/classes/relay-client.ts +++ b/packages/common/src/classes/relay-client.ts @@ -114,6 +114,10 @@ export class RelayClientBase { const timeoutIn = request.options.timeoutIn; if (timeoutIn) { subscription.options = { + view: + request.options && request.options.view + ? request.options.view + : "", timeoutIn, timeoutAt: Date.now() + timeoutIn, timeout: setTimeout(() => {