Refactor relay list a bit
tests / tests (push) Failing after 5m10s

This commit is contained in:
Jon Staab
2026-06-22 13:49:35 -07:00
parent 22a666d497
commit f97215de47
3 changed files with 63 additions and 71 deletions
+7 -2
View File
@@ -55,7 +55,10 @@ export class RelayLists extends DerivedPlugin<RelayList> {
return this.app.use(Thunks).publishToOutbox({event}) return this.app.use(Thunks).publishToOutbox({event})
} }
addRelay = (url: string, mode: RelayMode) => this.update(builder => builder.addUrl(url, mode)) addRelay = (url: string, mode: RelayMode) =>
this.update(builder =>
mode === RelayMode.Read ? builder.addReadUrl(url) : builder.addWriteUrl(url),
)
setReadRelays = (urls: string[]) => this.update(builder => builder.setReadUrls(urls)) setReadRelays = (urls: string[]) => this.update(builder => builder.setReadUrls(urls))
@@ -64,7 +67,9 @@ export class RelayLists extends DerivedPlugin<RelayList> {
removeRelay = async (url: string, mode: RelayMode) => { removeRelay = async (url: string, mode: RelayMode) => {
const user = User.require(this.app) const user = User.require(this.app)
const builder = new RelayListBuilder(await this.forceLoad(user.pubkey)) const builder = new RelayListBuilder(await this.forceLoad(user.pubkey))
const event = await builder.removeUrl(url, mode).toTemplate(user.signer) const event = await (
mode === RelayMode.Read ? builder.removeReadUrl(url) : builder.removeWriteUrl(url)
).toTemplate(user.signer)
// publishToOutbox is outbox-only, so build relays here to also notify the // publishToOutbox is outbox-only, so build relays here to also notify the
// removed relay of its removal // removed relay of its removal
+7 -7
View File
@@ -60,10 +60,10 @@ describe("RelayList", () => {
it("adds modeless and single-mode relays via a fresh builder", async () => { it("adds modeless and single-mode relays via a fresh builder", async () => {
const tmpl = await new RelayListBuilder() const tmpl = await new RelayListBuilder()
.addUrl(read, RelayMode.Read) .addReadUrl(read)
.addUrl(write, RelayMode.Write) .addWriteUrl(write)
.addUrl(both, RelayMode.Read) .addReadUrl(both)
.addUrl(both, RelayMode.Write) .addWriteUrl(both)
.toTemplate(signer) .toTemplate(signer)
expect(tmpl.kind).toBe(RELAYS) expect(tmpl.kind).toBe(RELAYS)
@@ -75,9 +75,9 @@ describe("RelayList", () => {
it("downgrades a modeless relay when one mode is removed", async () => { it("downgrades a modeless relay when one mode is removed", async () => {
const tmpl = await new RelayListBuilder() const tmpl = await new RelayListBuilder()
.addUrl(both, RelayMode.Read) .addReadUrl(both)
.addUrl(both, RelayMode.Write) .addWriteUrl(both)
.removeUrl(both, RelayMode.Read) .removeReadUrl(both)
.toTemplate(signer) .toTemplate(signer)
expect(tmpl.tags).toContainEqual(["r", both, RelayMode.Write]) expect(tmpl.tags).toContainEqual(["r", both, RelayMode.Write])
+49 -62
View File
@@ -1,32 +1,30 @@
import {uniq, uniqBy} from "@welshman/lib" import {nth, uniq, uniqBy, remove} from "@welshman/lib"
import {RELAYS, RelayMode, getRelayTags, getRelayTagValues, normalizeRelayUrl} from "@welshman/util" import {RELAYS, getRelayTags, normalizeRelayUrl} from "@welshman/util"
import {ListReader} from "../ListReader.js" import {ListReader} from "../ListReader.js"
import {ListBuilder} from "../ListBuilder.js" import {ListBuilder} from "../ListBuilder.js"
const getUrls = (tags: string[][], mode?: string) =>
uniqBy(
normalizeRelayUrl,
getRelayTags(tags)
.filter(t => !mode || !t[2] || t[2] === mode)
.map(nth(1)),
)
// NIP-65 kind-10002 relay list. // NIP-65 kind-10002 relay list.
export class RelayList extends ListReader { export class RelayList extends ListReader {
readonly kind = RELAYS readonly kind = RELAYS
urls() { urls() {
return uniqBy(normalizeRelayUrl, getRelayTagValues(this.tags())) return getUrls(this.tags())
} }
readUrls() { readUrls() {
return uniqBy( return getUrls(this.tags(), "read")
normalizeRelayUrl,
getRelayTags(this.tags())
.filter(t => !t[2] || t[2] === RelayMode.Read)
.map(t => t[1]),
)
} }
writeUrls() { writeUrls() {
return uniqBy( return getUrls(this.tags(), "write")
normalizeRelayUrl,
getRelayTags(this.tags())
.filter(t => !t[2] || t[2] === RelayMode.Write)
.map(t => t[1]),
)
} }
builder() { builder() {
@@ -37,73 +35,62 @@ export class RelayList extends ListReader {
export class RelayListBuilder extends ListBuilder<RelayList> { export class RelayListBuilder extends ListBuilder<RelayList> {
readonly kind = RELAYS readonly kind = RELAYS
readUrls() { addReadUrl(url: string) {
return uniqBy( return this.addUrlForMode(url, "read")
normalizeRelayUrl,
getRelayTags(this.publicTags)
.filter(t => !t[2] || t[2] === RelayMode.Read)
.map(t => t[1]),
)
} }
writeUrls() { addWriteUrl(url: string) {
return uniqBy( return this.addUrlForMode(url, "write")
normalizeRelayUrl,
getRelayTags(this.publicTags)
.filter(t => !t[2] || t[2] === RelayMode.Write)
.map(t => t[1]),
)
} }
addUrl(url: string, mode: RelayMode) { removeReadUrl(url: string) {
return this.removeUrlForMode(url, "read")
}
removeWriteUrl(url: string) {
return this.removeUrlForMode(url, "write")
}
private findUrlTag(url: string) {
const normalized = normalizeRelayUrl(url) const normalized = normalizeRelayUrl(url)
const existing = getRelayTags(this.publicTags).filter(
t => normalizeRelayUrl(t[1]) === normalized,
)
const priorModes = new Set<RelayMode | undefined>( return this.publicTags.find(t => t[0] === "r" && normalizeRelayUrl(t[1]) === normalized)
existing.map(t => t[2] as RelayMode | undefined), }
)
const alt = mode === RelayMode.Read ? RelayMode.Write : RelayMode.Read private addUrlForMode(url: string, mode: "read" | "write") {
const coversAlt = priorModes.has(undefined) || priorModes.has(alt) const existing = this.findUrlTag(url)
const alt = mode === "read" ? "write" : "read"
this.publicTags = this.publicTags.filter( if (!existing) {
t => !(t[0] === "r" && normalizeRelayUrl(t[1]) === normalized), this.publicTags.push(["r", normalizeRelayUrl(url), mode])
) } else if (existing[2] === alt) {
existing.splice(2)
this.publicTags.push(coversAlt ? ["r", url] : ["r", url, mode]) }
return this return this
} }
removeUrl(url: string, mode: RelayMode) { private removeUrlForMode(url: string, mode: "read" | "write") {
const normalized = normalizeRelayUrl(url) const existing = this.findUrlTag(url)
const existing = getRelayTags(this.publicTags).filter( const alt = mode === "read" ? "write" : "read"
t => normalizeRelayUrl(t[1]) === normalized,
)
const alt = mode === RelayMode.Read ? RelayMode.Write : RelayMode.Read if (existing) {
if (!existing[2]) {
const keepAlt = existing.some(t => !t[2] || t[2] === alt) existing[2] = alt
} else if (existing[2] === mode) {
this.publicTags = this.publicTags.filter( this.publicTags = remove(existing, this.publicTags)
t => !(t[0] === "r" && normalizeRelayUrl(t[1]) === normalized), }
)
if (keepAlt) {
this.publicTags.push(["r", url, alt])
} }
return this return this
} }
setReadUrls(urls: string[]) { setReadUrls(urls: string[]) {
return this.setUrlsForModes(urls, this.writeUrls()) return this.setUrlsForModes(urls, getUrls(this.publicTags, "write"))
} }
setWriteUrls(urls: string[]) { setWriteUrls(urls: string[]) {
return this.setUrlsForModes(this.readUrls(), urls) return this.setUrlsForModes(getUrls(this.publicTags, "read"), urls)
} }
private setUrlsForModes(readUrls: string[], writeUrls: string[]) { private setUrlsForModes(readUrls: string[], writeUrls: string[]) {
@@ -114,8 +101,8 @@ export class RelayListBuilder extends ListBuilder<RelayList> {
read.has(url) && write.has(url) read.has(url) && write.has(url)
? ["r", url] ? ["r", url]
: read.has(url) : read.has(url)
? ["r", url, RelayMode.Read] ? ["r", url, "read"]
: ["r", url, RelayMode.Write], : ["r", url, "write"],
) )
this.publicTags = [...otherTags, ...relayTags] this.publicTags = [...otherTags, ...relayTags]