Use MATH to figure out cursor window

This commit is contained in:
Jonathan Staab 2023-02-24 10:37:05 -06:00
parent 7c9223a37f
commit 4034eb3862
5 changed files with 27 additions and 17 deletions

View File

@ -1,9 +1,5 @@
# Current # Current
- [ ] Fix pagination
# Next
- [ ] Relay detail page, with more information about the relay + tabbed feeds (notes, more?) - [ ] Relay detail page, with more information about the relay + tabbed feeds (notes, more?)
- [ ] Add customize icon and route with editable custom view cards using "lists" nip - [ ] Add customize icon and route with editable custom view cards using "lists" nip
- nevent1qqspjcqw2hu5gfcpkrjhs0aqvxuzjgtp50l375mcqjfpmk48cg5hevgpr3mhxue69uhkummnw3ez6un9d3shjtnhd3m8xtnnwpskxegpzamhxue69uhkummnw3ezuendwsh8w6t69e3xj7spramhxue69uhkummnw3ez6un9d3shjtnwdahxxefwv93kzer9d4usz9rhwden5te0wfjkccte9ejxzmt4wvhxjmcpr9mhxue69uhkummnw3ezuer9d3hjuum0ve68wctjv5n8hwfg - nevent1qqspjcqw2hu5gfcpkrjhs0aqvxuzjgtp50l375mcqjfpmk48cg5hevgpr3mhxue69uhkummnw3ez6un9d3shjtnhd3m8xtnnwpskxegpzamhxue69uhkummnw3ezuendwsh8w6t69e3xj7spramhxue69uhkummnw3ez6un9d3shjtnwdahxxefwv93kzer9d4usz9rhwden5te0wfjkccte9ejxzmt4wvhxjmcpr9mhxue69uhkummnw3ezuer9d3hjuum0ve68wctjv5n8hwfg

View File

@ -72,12 +72,11 @@
const scroller = createScroller( const scroller = createScroller(
async () => { async () => {
await loadMessages(cursor, newMessages => { await loadMessages(cursor, newMessages => {
cursor.onChunk(newMessages)
stickToBottom('auto', () => { stickToBottom('auto', () => {
loading = sleep(30_000) loading = sleep(30_000)
messages = sortBy(e => -e.created_at, newMessages.concat(messages)) messages = sortBy(e => -e.created_at, newMessages.concat(messages))
network.loadPeople(pluck('pubkey', newMessages)) network.loadPeople(pluck('pubkey', newMessages))
cursor.update(messages)
}) })
}) })
}, },

View File

@ -1,5 +1,5 @@
import {debounce, throttle} from 'throttle-debounce' import {debounce, throttle} from 'throttle-debounce'
import {path as getPath, allPass, pipe, isNil, complement, equals, is, pluck, sum, identity, sortBy} from "ramda" import {aperture, path as getPath, allPass, pipe, isNil, complement, equals, is, pluck, sum, identity, sortBy} from "ramda"
import Fuse from "fuse.js/dist/fuse.min.js" import Fuse from "fuse.js/dist/fuse.min.js"
import {writable} from 'svelte/store' import {writable} from 'svelte/store'
import {isObject} from 'hurdak/lib/hurdak' import {isObject} from 'hurdak/lib/hurdak'
@ -152,14 +152,19 @@ export class Cursor {
this.until = now() this.until = now()
this.limit = limit this.limit = limit
} }
onChunk(events) { update(events) {
const minDelta = timedelta(1, 'minutes') // update takes all events in a feed and figures out the best place to set `until`
const maxDelta = timedelta(1, 'hours') // in order to find older events without re-fetching events that we've already seen.
const delta = pluck('created_at', events).reduce(Math.min, 0) || 0 // There are various edge cases:
// - When we have zero events, there's nothing we can do, presumably we have everything.
// - Sometimes relays send us extremely old events. Use median to avoid too-large gaps
if (events.length > 1) {
const timestamps = sortBy(identity, pluck('created_at', events))
const gaps = aperture(2, timestamps).map(([a, b]) => b - a)
const gap = quantile(gaps, 0.5)
// If the delta is very large, size it down. Relays with sparse data this.until -= Math.round(gap * events.length)
// can slide the window very quickly, skipping a lot of events on more dense relays }
this.until -= Math.max(minDelta, Math.min(maxDelta, delta))
} }
} }
@ -262,3 +267,14 @@ export const union = (...sets) =>
export const difference = (a, b) => export const difference = (a, b) =>
new Set(Array.from(a).filter(x => !b.has(x))) new Set(Array.from(a).filter(x => !b.has(x)))
export const quantile = (a, q) => {
const sorted = sortBy(identity, a)
const pos = (sorted.length - 1) * q
const base = Math.floor(pos)
const rest = pos - base
return isNil(sorted[base + 1])
? sorted[base]
: sorted[base] + rest * (sorted[base + 1] - sorted[base])
}

View File

@ -12,7 +12,7 @@
transition:fly={{y: -50, duration: 300}}> transition:fly={{y: -50, duration: 300}}>
<div <div
class={cx( class={cx(
"rounded shadow-xl mx-24 sm:mx-32 mt-2 p-3 text-center border pointer-events-auto", "rounded shadow-xl m-2 ml-16 sm:ml-2 p-3 text-center border pointer-events-auto",
"max-w-xl flex-grow transition-all", "max-w-xl flex-grow transition-all",
{ {
'bg-dark border-medium text-white': $toast.type === 'info', 'bg-dark border-medium text-white': $toast.type === 'info',

View File

@ -68,8 +68,7 @@
notes = uniqBy(prop('id'), notes.concat(bottom)) notes = uniqBy(prop('id'), notes.concat(bottom))
notesBuffer = top.concat(notesBuffer).slice(0, maxNotes) notesBuffer = top.concat(notesBuffer).slice(0, maxNotes)
// Check all notes every time to stay very conservative with moving the window cursor.update(notes)
cursor.onChunk(notes)
} }
onMount(() => { onMount(() => {