Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
152214591a
3 changed files with 67 additions and 20 deletions
|
|
@ -1715,6 +1715,8 @@ Acceptance:
|
|||
drawn underneath it, and never appears as an item of its own.
|
||||
- Every note carries its reply count, including the ones with no replies.
|
||||
- Scrolling to the end of the feed loads more rather than asking her to.
|
||||
- The feed is one unbroken stretch back from now, so nothing appears below the
|
||||
end of the list.
|
||||
- The section fills from the relays that answer. One that takes the connection
|
||||
and then says nothing does not hold it empty.
|
||||
|
||||
|
|
|
|||
|
|
@ -507,6 +507,56 @@ test("US-117 read a follow who is in none of your spaces", async ({seed, as}) =>
|
|||
expect(fromSpace).toEqual([])
|
||||
})
|
||||
|
||||
test("US-117 read a network feed whose relays answer from different depths", async ({seed, as}) => {
|
||||
// Mirrors PAGE_SIZE: a full page covers only as far back as it reaches.
|
||||
const pageSize = 100
|
||||
const recent = "the harbourmaster moved the moorings again"
|
||||
const deep = "the old crane was scrapped in the spring"
|
||||
|
||||
await seed(({relay, open, user, at}) => {
|
||||
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, outbox.url],
|
||||
})
|
||||
indexer.follows(user.alice, [user.bob])
|
||||
|
||||
// Bob's outbox holds a full page of recent notes, the indexer one week-old note.
|
||||
indexer.relayList(user.bob, {read: [outbox.url], write: [outbox.url, indexer.url]})
|
||||
outbox.profile(user.bob, {name: "Bob Barker"})
|
||||
|
||||
outbox.note(user.bob, recent, at(1, MINUTE))
|
||||
|
||||
// More than pageSize so the page comes back full.
|
||||
for (let minute = 2; minute <= pageSize + 10; minute++) {
|
||||
outbox.note(user.bob, `mooring report ${minute}`, at(minute, MINUTE))
|
||||
}
|
||||
|
||||
indexer.note(user.bob, deep, at(7, DAY))
|
||||
})
|
||||
|
||||
const page = await as(users.alice, "/home")
|
||||
|
||||
const network = page
|
||||
.locator("section")
|
||||
.filter({has: page.getByRole("heading", {name: "Network"})})
|
||||
|
||||
await expect(network.getByText(recent)).toBeVisible()
|
||||
|
||||
// Below the stretch the outbox covered, so it is held until the scroll.
|
||||
await expect(network.getByText(deep)).toHaveCount(0)
|
||||
|
||||
await network.locator(".card").last().scrollIntoViewIfNeeded()
|
||||
|
||||
await expect(network.getByText(deep)).toBeVisible()
|
||||
})
|
||||
|
||||
test("US-117 read the network feed when one relay never answers", async ({seed, as}) => {
|
||||
// Nothing serves this url, and nothing needs to: the fault is a relay that takes the socket and
|
||||
// then says nothing, which is all the spec asks of it.
|
||||
|
|
|
|||
|
|
@ -375,11 +375,15 @@ export type FeedLoadState =
|
|||
// nothing in it, and the two have to move the window differently.
|
||||
export type FeedSpan = {found: number; complete: boolean; exhausted: boolean}
|
||||
|
||||
// The share of the relays a span asked that have to answer before it stops waiting on the rest. A
|
||||
// request otherwise waits on every one of them, and a relay that accepts a socket and then says
|
||||
// nothing neither answers nor drops. A span is also what releases the events it found, so one
|
||||
// silent relay leaves the feed empty rather than slow.
|
||||
const SPAN_THRESHOLD = 0.5
|
||||
// Relatively high because quiet relays eose first.
|
||||
const SPAN_THRESHOLD = 0.8
|
||||
|
||||
// Short because a relay can accept a socket and never eose.
|
||||
const SPAN_TIMEOUT = 3000
|
||||
|
||||
// Abort resolves a request with what arrived.
|
||||
const spanSignal = (signal: AbortSignal) =>
|
||||
AbortSignal.any([signal, AbortSignal.timeout(SPAN_TIMEOUT)])
|
||||
|
||||
// Empty spans to walk per trigger. Enough to cross a gap; not enough to reach the end of the
|
||||
// history on a single request.
|
||||
|
|
@ -530,8 +534,6 @@ export const makeFeed = ({
|
|||
}
|
||||
}
|
||||
|
||||
// What arrives from elsewhere in the app, which is only rendered as far back as the feed has
|
||||
// got to on its own
|
||||
const addEvents = (newEvents: TrustedEvent[]) => {
|
||||
const ready: TrustedEvent[] = []
|
||||
|
||||
|
|
@ -599,7 +601,7 @@ export const makeFeed = ({
|
|||
const found = await network.get().request({
|
||||
relays,
|
||||
autoClose: true,
|
||||
signal: controller.signal,
|
||||
signal: spanSignal(controller.signal),
|
||||
threshold: SPAN_THRESHOLD,
|
||||
filters: filters.map(filter => ({...filter, ...extension})),
|
||||
onEvent: countEvent,
|
||||
|
|
@ -644,7 +646,8 @@ export const makeFeed = ({
|
|||
oldest = edge === undefined ? since : Math.min(edge, until - 1)
|
||||
}
|
||||
|
||||
insertEvents(found)
|
||||
// addEvents, not insertEvents: found can reach below oldest.
|
||||
addEvents(found)
|
||||
reach(oldest)
|
||||
|
||||
return {found: found.length, complete, exhausted: false}
|
||||
|
|
@ -666,20 +669,12 @@ export const makeFeed = ({
|
|||
newest = until
|
||||
}
|
||||
|
||||
insertEvents(found)
|
||||
addEvents(found)
|
||||
|
||||
return {found: found.length, complete, exhausted: false}
|
||||
}
|
||||
|
||||
// What the repository already holds for these relays is in hand and goes in as one insert,
|
||||
// which takes the window back with it rather than leaving the rest of that stretch behind
|
||||
const cached = relays.flatMap(url => Array.from(getEventsForUrl(url, filters)))
|
||||
|
||||
for (const event of cached) {
|
||||
reached = Math.min(reached, event.created_at)
|
||||
}
|
||||
|
||||
insertEvents(cached)
|
||||
addEvents(relays.flatMap(url => Array.from(getEventsForUrl(url, filters))))
|
||||
|
||||
return {
|
||||
events,
|
||||
|
|
@ -775,7 +770,7 @@ export const makeCalendarFeed = ({
|
|||
const found = await network.get().request({
|
||||
relays,
|
||||
autoClose: true,
|
||||
signal: controller.signal,
|
||||
signal: spanSignal(controller.signal),
|
||||
threshold: SPAN_THRESHOLD,
|
||||
filters: [{kinds: [EVENT_TIME], "#D": daysBetween(since, until).map(String)}],
|
||||
onEose: () => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue