From c5364b60b83d23af5e210fa8df78395d291cb440 Mon Sep 17 00:00:00 2001 From: Jon Staab Date: Wed, 11 Sep 2024 14:07:34 -0700 Subject: [PATCH] Put tracker in a store --- packages/app/src/core.ts | 13 ++++++++++++- packages/app/src/storage.ts | 21 ++++++++++++++++++++- packages/app/src/thunk.ts | 6 +++++- packages/net/src/Tracker.ts | 5 +++++ packages/store/src/index.ts | 26 ++++++++++++++++++++++---- packages/util/src/Relay.ts | 1 + 6 files changed, 65 insertions(+), 7 deletions(-) diff --git a/packages/app/src/core.ts b/packages/app/src/core.ts index e4b7834..77a7531 100644 --- a/packages/app/src/core.ts +++ b/packages/app/src/core.ts @@ -3,7 +3,7 @@ import {Repository, Relay, LOCAL_RELAY_URL, getFilterResultCardinality} from "@w import type {TrustedEvent, Filter} from "@welshman/util" import {Tracker, subscribe as baseSubscribe} from "@welshman/net" import type {SubscribeRequestWithHandlers} from "@welshman/net" -import {createEventStore} from "@welshman/store" +import {createEventStore, custom} from "@welshman/store" export const repository = new Repository() @@ -13,6 +13,17 @@ export const relay = new Relay(repository) export const tracker = new Tracker() +export const trackerStore = custom(setter => { + const onUpdate = () => setter(tracker) + + onUpdate() + tracker.on('update', onUpdate) + + return () => tracker.off('update', onUpdate) +}, { + set: (other: Tracker) => tracker.load(other.data), +}) + export type PartialSubscribeRequest = Partial & {filters: Filter[]} export const subscribe = (request: PartialSubscribeRequest) => { diff --git a/packages/app/src/storage.ts b/packages/app/src/storage.ts index f331a07..98cb03f 100644 --- a/packages/app/src/storage.ts +++ b/packages/app/src/storage.ts @@ -4,7 +4,8 @@ import {throttle} from "throttle-debounce" import {writable} from "svelte/store" import type {Unsubscriber, Writable} from "svelte/store" import {randomInt, fromPairs} from "@welshman/lib" -import {withGetter, adapter} from "@welshman/store" +import type {Tracker} from "@welshman/net" +import {withGetter, adapter, custom} from "@welshman/store" export type Item = Record @@ -141,4 +142,22 @@ export const storageAdapters = { new Map(data.map(({key, value}) => [key, value])), }), }), + fromTracker: (tracker: Tracker) => ({ + keyPath: 'key', + store: custom(setter => { + const onUpdate = () => + setter( + Array.from(tracker.data.entries()) + .map(([key, urls]) => ({key, value: Array.from(urls)})) + ) + + onUpdate() + tracker.on('update', onUpdate) + + return () => tracker.off('update', onUpdate) + }, { + set: (data: {key: string, value: string[]}[]) => + tracker.load(new Map(data.map(({key, value}) => [key, new Set(value)]))), + }), + }), } diff --git a/packages/app/src/thunk.ts b/packages/app/src/thunk.ts index 978af05..d328eac 100644 --- a/packages/app/src/thunk.ts +++ b/packages/app/src/thunk.ts @@ -3,7 +3,7 @@ import {Worker, assoc} from '@welshman/lib' import {stamp, own, hash} from "@welshman/signer" import type {HashedEvent, EventTemplate, SignedEvent} from '@welshman/util' import {publish, PublishStatus} from "@welshman/net" -import {repository} from './core' +import {repository, tracker} from './core' import {pubkey, getSession, getSigner} from './session' export type PublishStatusData = { @@ -52,6 +52,10 @@ thunkWorker.addGlobalHandler(async ({event, relays, resolve}: ThunkWithResolve) assoc(id, Object.assign(statusByUrl, {[url]: {id, url, status, message}})), ) + if (status === PublishStatus.Success) { + tracker.track(id, url) + } + if ( Object.values(statusByUrl).filter(s => s.status !== PublishStatus.Pending).length === relays.length diff --git a/packages/net/src/Tracker.ts b/packages/net/src/Tracker.ts index f188178..5e06cb5 100644 --- a/packages/net/src/Tracker.ts +++ b/packages/net/src/Tracker.ts @@ -46,6 +46,11 @@ export class Tracker extends Emitter { } } + load = (data: Tracker['data']) => { + this.data = data + this.emit('update') + } + clear = () => { this.data.clear() this.emit('update') diff --git a/packages/store/src/index.ts b/packages/store/src/index.ts index cb314ce..ae3bcf2 100644 --- a/packages/store/src/index.ts +++ b/packages/store/src/index.ts @@ -28,15 +28,23 @@ export const getter = (store: Readable) => { return () => value } -export function withGetter(store: Writable): Writable & {get: () => T} -export function withGetter(store: Readable): Readable & {get: () => T} +export type WritableWithGetter = Writable & {get: () => T} +export type ReadableWithGetter = Readable & {get: () => T} + +export function withGetter(store: Writable): WritableWithGetter +export function withGetter(store: Readable): ReadableWithGetter export function withGetter(store: Readable | Writable) { return {...store, get: getter(store)} } type Start = (set: Subscriber) => Unsubscriber -export const custom = (start: Start, opts: {throttle?: number} = {}) => { +export type CustomStoreOpts = { + throttle?: number + set?: (x: T) => void +} + +export const custom = (start: Start, opts: CustomStoreOpts = {}): WritableWithGetter => { const subs: Subscriber[] = [] let value: T @@ -51,7 +59,17 @@ export const custom = (start: Start, opts: {throttle?: number} = {}) => { } return { - set, + get: () => value, + set: (newValue: T) => { + set(newValue) + opts.set?.(newValue) + }, + update: (f: (value: T) => T) => { + const newValue = f(value) + + set(newValue) + opts.set?.(newValue) + }, subscribe: (sub: Subscriber) => { if (opts.throttle) { sub = throttle(opts.throttle, sub) diff --git a/packages/util/src/Relay.ts b/packages/util/src/Relay.ts index 6d93b24..edba3b1 100644 --- a/packages/util/src/Relay.ts +++ b/packages/util/src/Relay.ts @@ -12,6 +12,7 @@ export const BOGUS_RELAY_URL = "bogus://welshman.relay" export type RelayProfile = { url: string + icon?: string name?: string pubkey?: string contact?: string