Ask a search relay whether it supports search before offering to drop it (#659)
This commit is contained in:
parent
1c934576fe
commit
653664751f
4 changed files with 86 additions and 4 deletions
|
|
@ -1724,6 +1724,18 @@ Acceptance:
|
|||
- The section fills from the relays that answer. One that takes the connection
|
||||
and then says nothing does not hold it empty.
|
||||
|
||||
### US-133 — Keep the search relays that work
|
||||
|
||||
As alice, I want the search health check to leave alone the relays that do
|
||||
support search, so that fixing it does not cost me the ones I chose.
|
||||
|
||||
Acceptance:
|
||||
|
||||
- The check reads each search relay's own metadata, so a relay that advertises
|
||||
search is never offered for removal, and neither is one whose metadata never
|
||||
arrives.
|
||||
- A relay that answers and advertises no search is.
|
||||
|
||||
### US-106 — Share text into the app
|
||||
|
||||
As alice, I want to hand text to Flotilla and choose where it lands, so that I
|
||||
|
|
|
|||
|
|
@ -2,7 +2,15 @@ import {neventEncode, npubEncode} from "nostr-tools/nip19"
|
|||
import {DAY, HOUR, MINUTE} from "@welshman/lib"
|
||||
import {POLL, displayRelayUrl} from "@welshman/util"
|
||||
import {RelayMessageType} from "@welshman/net"
|
||||
import {Classified, Comment, FollowList, Note, Poll, Thread} from "@welshman/domain"
|
||||
import {
|
||||
Classified,
|
||||
Comment,
|
||||
FollowList,
|
||||
Note,
|
||||
Poll,
|
||||
SearchRelayList,
|
||||
Thread,
|
||||
} from "@welshman/domain"
|
||||
import type {Locator, Page} from "@playwright/test"
|
||||
import {
|
||||
composer,
|
||||
|
|
@ -560,6 +568,54 @@ test("US-117 read the network feed when one relay never answers", async ({seed,
|
|||
await expect(network.getByText("Bob Barker")).toBeVisible()
|
||||
})
|
||||
|
||||
// A url the container does not serve, so its nip-11 document never arrives and nothing knows what it supports.
|
||||
const unreachableRelayUrl = "wss://unreachable.test/"
|
||||
|
||||
test("US-133 keep the search relays that support search", async ({seed, as}) => {
|
||||
const scenario = await seed(({relay, open, user}) => {
|
||||
const space = relay("space")
|
||||
const indexer = open("indexer")
|
||||
const outbox = open("outbox")
|
||||
|
||||
space.room("general", {name: "General"})
|
||||
space.join(user.alice, "general")
|
||||
|
||||
indexer.relayList(user.alice, {
|
||||
read: [space.url, indexer.url],
|
||||
write: [space.url, indexer.url],
|
||||
})
|
||||
|
||||
// No search relay of hers is a space, so the health check is the only thing asking for their metadata.
|
||||
indexer.event(user.alice, () =>
|
||||
indexer
|
||||
.kind(SearchRelayList)
|
||||
.writer()
|
||||
.setUrls([indexer.url, outbox.url, unreachableRelayUrl])
|
||||
.renderTemplate(),
|
||||
)
|
||||
})
|
||||
|
||||
const indexer = scenario.open("indexer")
|
||||
const outbox = scenario.open("outbox")
|
||||
|
||||
const page = await as(users.alice, "/home", {
|
||||
relayInfo: {[indexer.url]: {supported_nips: [1, 50]}},
|
||||
})
|
||||
|
||||
const healthCheck = page.getByRole("group", {name: "Invalid Search Relays"})
|
||||
|
||||
await expect(healthCheck).toBeVisible()
|
||||
|
||||
await healthCheck.getByRole("button", {name: "Fix"}).click()
|
||||
|
||||
const review = dialog(page, "Review changes")
|
||||
|
||||
// Outbox answered and advertised no search; the other two are a relay that does and one nobody can ask.
|
||||
await expect(review.getByText(displayRelayUrl(outbox.url))).toBeVisible()
|
||||
await expect(review.getByText(displayRelayUrl(indexer.url))).toHaveCount(0)
|
||||
await expect(review.getByText(displayRelayUrl(unreachableRelayUrl))).toHaveCount(0)
|
||||
})
|
||||
|
||||
test("US-106 share text into the app", async ({seed, as}) => {
|
||||
const shared = "the offsite is moving to the 14th"
|
||||
|
||||
|
|
|
|||
|
|
@ -109,13 +109,15 @@ export class HealthChecks {
|
|||
)
|
||||
|
||||
this.pending = projection(
|
||||
derived([this.context.$, forceHealthChecks], ([$context, $forceHealthChecks]) =>
|
||||
this.checks.filter(check => $forceHealthChecks[check.id] ?? check.isPending($context)),
|
||||
derived(
|
||||
[this.context.$, forceHealthChecks, app.use(Relays).index.$],
|
||||
([$context, $forceHealthChecks]) =>
|
||||
this.checks.filter(check => $forceHealthChecks[check.id] ?? check.isPending($context)),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private supportsSearch = (url: string) => this.app.use(Relays).get(url)?.hasNip(50)
|
||||
private supportsSearch = (url: string) => this.app.use(Relays).get(url)?.hasNip(50) ?? true
|
||||
|
||||
private checks: HealthCheck[] = [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import {
|
|||
MessagingRelayLists,
|
||||
RelayLists,
|
||||
RoomLists,
|
||||
SearchRelayLists,
|
||||
Sync,
|
||||
makeRoomKey,
|
||||
} from "@welshman/app"
|
||||
|
|
@ -53,6 +54,7 @@ import {
|
|||
relays,
|
||||
roomLists,
|
||||
router,
|
||||
searchRelayLists,
|
||||
} from "@app/core"
|
||||
import {LIVEKIT_PARTICIPANTS} from "@app/call"
|
||||
import {REACTION_KINDS, CONTENT_KINDS, makeCommentFilter} from "@app/content"
|
||||
|
|
@ -100,6 +102,8 @@ const userFollowList = deriveUserItem(FollowLists)
|
|||
|
||||
const userMessagingRelayList = deriveUserItem(MessagingRelayLists)
|
||||
|
||||
const userSearchRelayList = deriveUserItem(SearchRelayLists)
|
||||
|
||||
const getSpaceUrls = ($roomList: Maybe<RoomListReader>) =>
|
||||
PLATFORM_RELAYS.length > 0 ? PLATFORM_RELAYS : ($roomList?.urls() ?? [])
|
||||
|
||||
|
|
@ -125,9 +129,16 @@ const syncRelays = () => {
|
|||
}
|
||||
})
|
||||
|
||||
const unsubscribeSearchRelayUrls = userSearchRelayList.subscribe($searchRelayList => {
|
||||
for (const url of $searchRelayList?.urls() ?? []) {
|
||||
relays.get().load(url)
|
||||
}
|
||||
})
|
||||
|
||||
return () => {
|
||||
unsubscribePage()
|
||||
unsubscribeSpaceUrls()
|
||||
unsubscribeSearchRelayUrls()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -213,6 +224,7 @@ const syncUserData = () => {
|
|||
roomLists.get().load($pubkey)
|
||||
muteLists.get().load($pubkey)
|
||||
profiles.get().load($pubkey)
|
||||
searchRelayLists.get().load($pubkey)
|
||||
app.get().use(Settings).load($pubkey)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue