diff --git a/packages/app/src/relays.ts b/packages/app/src/relays.ts index 01ec715..9dcd86a 100644 --- a/packages/app/src/relays.ts +++ b/packages/app/src/relays.ts @@ -1,6 +1,6 @@ import {writable, derived} from 'svelte/store' import {withGetter} from '@welshman/store' -import {groupBy, batch, nth, now, uniq, uniqBy, batcher, postJson} from '@welshman/lib' +import {groupBy, indexBy, batch, now, uniq, uniqBy, batcher, postJson} from '@welshman/lib' import {type RelayProfile} from "@welshman/util" import {AuthStatus, asMessage, type Connection, type SocketMessage} from '@welshman/net' import {env} from './core' @@ -99,28 +99,28 @@ export const relaySearch = derived(relays, $relays => type RelayStatsUpdate = [string, (stats: RelayStats) => void] const updateRelayStats = batch(500, (updates: RelayStatsUpdate[]) => { - const updatesByUrl = groupBy(nth(0), updates) + relays.update(($relays: Relay[]) => { + const $relaysByUrl = indexBy(r => r.url, $relays) + const $itemsByUrl = groupBy(([url]) => url, updates) - relays.update($relays => { - return $relays.map($relay => { - for (const [_, update] of updatesByUrl.get($relay.url) || []) { - if (!$relay.stats) { - $relay.stats = makeRelayStats() - } + for (const [url, items] of $itemsByUrl.entries()) { + const $relay: Relay = $relaysByUrl.get(url) || {url} + if (!$relay.stats) { + $relay.stats = makeRelayStats() + } + + for (const [_, update] of items) { update($relay.stats) } - return $relay - }) + $relaysByUrl.set(url, $relay) + } + + return Array.from($relaysByUrl.values()) }) }) -const onConnectionError = ({url}: Connection) => - updateRelayStats([url, stats => { - stats.recent_errors = stats.recent_errors.concat(now()).slice(-10) - }]) - const onConnectionSend = ({url}: Connection, socketMessage: SocketMessage) => { const [verb] = asMessage(socketMessage) @@ -153,18 +153,23 @@ const onConnectionReceive = ({url}: Connection, socketMessage: SocketMessage) => } } +const onConnectionFault = ({url}: Connection) => + updateRelayStats([url, stats => { + stats.recent_errors = stats.recent_errors.concat(now()).slice(-10) + }]) + export const trackRelayStats = (connection: Connection) => { updateRelayStats([connection.url, stats => { stats.connect_count = stats.connect_count + 1 }]) - connection.on('error', onConnectionError) connection.on('send', onConnectionSend) connection.on('receive', onConnectionReceive) + connection.on('fault', onConnectionFault) return () => { - connection.off('error', onConnectionError) connection.off('send', onConnectionSend) connection.off('receive', onConnectionReceive) + connection.off('fault', onConnectionFault) } } diff --git a/packages/net/src/Connection.ts b/packages/net/src/Connection.ts index 618aa3b..def9c10 100644 --- a/packages/net/src/Connection.ts +++ b/packages/net/src/Connection.ts @@ -83,7 +83,7 @@ export class Connection extends Emitter { onClose = () => this.emit('close', this) - onError = () => this.emit('fault', this) + onFault = () => this.emit('fault', this) onMessage = (m: SocketMessage) => this.receiver.push(m) diff --git a/packages/net/src/Socket.ts b/packages/net/src/Socket.ts index 2651064..1f486f2 100644 --- a/packages/net/src/Socket.ts +++ b/packages/net/src/Socket.ts @@ -14,7 +14,7 @@ export const asMessage = (m: SocketMessage): Message => isMessage(m) ? m : m[1] export type SocketOpts = { onOpen: () => void onClose: () => void - onError: () => void + onFault: () => void onMessage: (message: SocketMessage) => void } @@ -59,12 +59,12 @@ export class Socket { try { this.ws = new WebSocket(this.url) this.ws.onopen = this.opts.onOpen - this.ws.onerror = this.opts.onError + this.ws.onerror = this.opts.onFault this.ws.onclose = this.opts.onClose this.ws.onmessage = this.onMessage } catch (e) { this.ws = 'invalid' - this.opts.onError() + this.opts.onFault() } while (this.isConnecting()) {