import {Emitter, addToMapKey} from "@welshman/lib" export class Tracker extends Emitter { relaysById = new Map>() idsByRelay = new Map>() constructor() { super() this.setMaxListeners(100) } getIds = (relay: string) => this.idsByRelay.get(relay) || new Set() getRelays = (eventId: string) => this.relaysById.get(eventId) || new Set() hasRelay = (eventId: string, relay: string) => this.relaysById.get(eventId)?.has(relay) addRelay = (eventId: string, relay: string) => { let relays = this.relaysById.get(eventId) let ids = this.idsByRelay.get(relay) if (relays?.has(relay) && ids?.has(eventId)) return if (!relays) { relays = new Set() } if (!ids) { ids = new Set() } relays.add(relay) ids.add(eventId) this.relaysById.set(eventId, relays) this.idsByRelay.set(relay, ids) this.emit("add", eventId, relay) } removeRelay = (eventId: string, relay: string) => { const didDeleteRelay = this.relaysById.get(eventId)?.delete(relay) ?? false const didDeleteId = this.idsByRelay.get(relay)?.delete(eventId) ?? false if (!didDeleteRelay || !didDeleteId) return this.emit("remove", eventId, relay) } track = (eventId: string, relay: string) => { const seen = this.relaysById.has(eventId) this.addRelay(eventId, relay) return seen } copy = (eventId1: string, eventId2: string) => { for (const relay of this.getRelays(eventId1)) { this.addRelay(eventId2, relay) } } load = (relaysById: Tracker["relaysById"]) => { this.relaysById.clear() this.idsByRelay.clear() for (const [id, relays] of relaysById.entries()) { for (const relay of relays) { addToMapKey(this.relaysById, id, relay) addToMapKey(this.idsByRelay, relay, id) } } this.emit("load") } clear = () => { this.relaysById.clear() this.idsByRelay.clear() this.emit("clear") } }