Wait for most of a span's relays, with a three second ceiling
This commit is contained in:
parent
d905c9dc1b
commit
eb9323a88b
3 changed files with 18 additions and 26 deletions
|
|
@ -1715,9 +1715,8 @@ Acceptance:
|
||||||
drawn underneath it, and never appears as an item of its own.
|
drawn underneath it, and never appears as an item of its own.
|
||||||
- Every note carries its reply count, including the ones with no replies.
|
- 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.
|
- Scrolling to the end of the feed loads more rather than asking her to.
|
||||||
- The feed is one unbroken stretch back from now. A relay that answers a page
|
- The feed is one unbroken stretch back from now, so nothing appears below the
|
||||||
from further back than the rest have been asked about waits for the feed to
|
end of the list.
|
||||||
reach it, so nothing lands below the end of the list.
|
|
||||||
- The section fills from the relays that answer. One that takes the connection
|
- The section fills from the relays that answer. One that takes the connection
|
||||||
and then says nothing does not hold it empty.
|
and then says nothing does not hold it empty.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -508,8 +508,7 @@ test("US-117 read a follow who is in none of your spaces", async ({seed, as}) =>
|
||||||
})
|
})
|
||||||
|
|
||||||
test("US-117 read a network feed whose relays answer from different depths", async ({seed, as}) => {
|
test("US-117 read a network feed whose relays answer from different depths", async ({seed, as}) => {
|
||||||
// What each relay is asked for one page at a time. A relay that fills its page has only covered
|
// A relay that fills its page has covered only as far back as the page reaches.
|
||||||
// as far back as the page reaches, so a busy one is what decides how far the feed has got.
|
|
||||||
const pageSize = 100
|
const pageSize = 100
|
||||||
const recent = "the harbourmaster moved the moorings again"
|
const recent = "the harbourmaster moved the moorings again"
|
||||||
const deep = "the old crane was scrapped in the spring"
|
const deep = "the old crane was scrapped in the spring"
|
||||||
|
|
@ -528,8 +527,7 @@ test("US-117 read a network feed whose relays answer from different depths", asy
|
||||||
})
|
})
|
||||||
indexer.follows(user.alice, [user.bob])
|
indexer.follows(user.alice, [user.bob])
|
||||||
|
|
||||||
// Bob writes to both, so the feed asks both. His busy relay holds more than one page of the
|
// Bob's busy relay holds a page of the last two hours, his quiet one a week-old note.
|
||||||
// last couple of hours; his quiet one holds a single note from a week ago.
|
|
||||||
indexer.relayList(user.bob, {read: [outbox.url], write: [outbox.url, indexer.url]})
|
indexer.relayList(user.bob, {read: [outbox.url], write: [outbox.url, indexer.url]})
|
||||||
outbox.profile(user.bob, {name: "Bob Barker"})
|
outbox.profile(user.bob, {name: "Bob Barker"})
|
||||||
|
|
||||||
|
|
@ -551,12 +549,9 @@ test("US-117 read a network feed whose relays answer from different depths", asy
|
||||||
|
|
||||||
await expect(network.getByText(recent)).toBeVisible()
|
await expect(network.getByText(recent)).toBeVisible()
|
||||||
|
|
||||||
// The quiet relay answered from a week back, which is days below where the busy one has been
|
// A week back is days below where the busy relay has been asked about, so it is held.
|
||||||
// asked about. Drawing it would put a note under the end of the list with the whole week
|
|
||||||
// between still missing.
|
|
||||||
await expect(network.getByText(deep)).toHaveCount(0)
|
await expect(network.getByText(deep)).toHaveCount(0)
|
||||||
|
|
||||||
// It is held rather than dropped, so the feed hands it over once it has paged back that far.
|
|
||||||
await network.locator(".card").last().scrollIntoViewIfNeeded()
|
await network.locator(".card").last().scrollIntoViewIfNeeded()
|
||||||
|
|
||||||
await expect(network.getByText(deep)).toBeVisible()
|
await expect(network.getByText(deep)).toBeVisible()
|
||||||
|
|
|
||||||
|
|
@ -375,11 +375,15 @@ export type FeedLoadState =
|
||||||
// nothing in it, and the two have to move the window differently.
|
// nothing in it, and the two have to move the window differently.
|
||||||
export type FeedSpan = {found: number; complete: boolean; exhausted: boolean}
|
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
|
// How far a span covered is set by its least generous relay, and quiet relays answer first.
|
||||||
// request otherwise waits on every one of them, and a relay that accepts a socket and then says
|
const SPAN_THRESHOLD = 0.8
|
||||||
// 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.
|
// A relay that accepts a socket and then says nothing neither answers nor drops.
|
||||||
const SPAN_THRESHOLD = 0.5
|
const SPAN_TIMEOUT = 3000
|
||||||
|
|
||||||
|
// Aborting a request resolves it with what arrived, the same way closing it does.
|
||||||
|
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
|
// Empty spans to walk per trigger. Enough to cross a gap; not enough to reach the end of the
|
||||||
// history on a single request.
|
// history on a single request.
|
||||||
|
|
@ -530,8 +534,7 @@ export const makeFeed = ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The one door into the feed, so that what it renders is one unbroken stretch back from the
|
// The one door into the feed, and anything older than it has reached waits for the window.
|
||||||
// anchor: anything older than the feed has reached waits there until the window gets to it.
|
|
||||||
const addEvents = (newEvents: TrustedEvent[]) => {
|
const addEvents = (newEvents: TrustedEvent[]) => {
|
||||||
const ready: TrustedEvent[] = []
|
const ready: TrustedEvent[] = []
|
||||||
|
|
||||||
|
|
@ -599,7 +602,7 @@ export const makeFeed = ({
|
||||||
const found = await network.get().request({
|
const found = await network.get().request({
|
||||||
relays,
|
relays,
|
||||||
autoClose: true,
|
autoClose: true,
|
||||||
signal: controller.signal,
|
signal: spanSignal(controller.signal),
|
||||||
threshold: SPAN_THRESHOLD,
|
threshold: SPAN_THRESHOLD,
|
||||||
filters: filters.map(filter => ({...filter, ...extension})),
|
filters: filters.map(filter => ({...filter, ...extension})),
|
||||||
onEvent: countEvent,
|
onEvent: countEvent,
|
||||||
|
|
@ -644,10 +647,7 @@ export const makeFeed = ({
|
||||||
oldest = edge === undefined ? since : Math.min(edge, until - 1)
|
oldest = edge === undefined ? since : Math.min(edge, until - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A span reaches further back than it covers. A relay holding few of these authors answers
|
// A span reaches further back than it covers, so its deepest events wait for the window.
|
||||||
// a page from days deeper than a busy one does, and rendering that stretch leaves a list
|
|
||||||
// whose bottom is a scatter the window then fills in above — so it waits for the window
|
|
||||||
// like anything else arriving early.
|
|
||||||
addEvents(found)
|
addEvents(found)
|
||||||
reach(oldest)
|
reach(oldest)
|
||||||
|
|
||||||
|
|
@ -675,8 +675,6 @@ export const makeFeed = ({
|
||||||
return {found: found.length, complete, exhausted: false}
|
return {found: found.length, complete, exhausted: false}
|
||||||
}
|
}
|
||||||
|
|
||||||
// What the repository already holds is a scatter rather than a stretch — an earlier visit's
|
|
||||||
// pages, a reply pulled in as context from weeks back — so it waits for the window too.
|
|
||||||
addEvents(relays.flatMap(url => Array.from(getEventsForUrl(url, filters))))
|
addEvents(relays.flatMap(url => Array.from(getEventsForUrl(url, filters))))
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -773,7 +771,7 @@ export const makeCalendarFeed = ({
|
||||||
const found = await network.get().request({
|
const found = await network.get().request({
|
||||||
relays,
|
relays,
|
||||||
autoClose: true,
|
autoClose: true,
|
||||||
signal: controller.signal,
|
signal: spanSignal(controller.signal),
|
||||||
threshold: SPAN_THRESHOLD,
|
threshold: SPAN_THRESHOLD,
|
||||||
filters: [{kinds: [EVENT_TIME], "#D": daysBetween(since, until).map(String)}],
|
filters: [{kinds: [EVENT_TIME], "#D": daysBetween(since, until).map(String)}],
|
||||||
onEose: () => {
|
onEose: () => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue