Speed up loadParents

This commit is contained in:
Jonathan Staab 2023-02-21 15:43:16 -06:00
parent d9414b2a27
commit 5ce930f0d0
10 changed files with 52 additions and 27 deletions

View File

@ -1,10 +1,7 @@
# Current # Current
- [ ] Fix loading routes speed, index by pubkey to avoid filtering
- [ ] Include everyone in person list modal, re-fetch missing people
- [ ] Fix initial relay loading, don't nuke people's relay lists - [ ] Fix initial relay loading, don't nuke people's relay lists
- [ ] Add a nuclear bypass with a warning, after we fail to find anything - [ ] Add a nuclear bypass with a warning, after we fail to find anything
- [ ] Don't waste space caching rooms, load those lazily
# Next # Next
@ -33,6 +30,7 @@
- [ ] open web+nostr links like snort - [ ] open web+nostr links like snort
- [ ] Channels - [ ] Channels
- [ ] Separate chat and DMs - [ ] Separate chat and DMs
- [ ] Don't waste space caching rooms, load those lazily
- [ ] Damus has chats divided into DMs and requests - [ ] Damus has chats divided into DMs and requests
- [ ] Ability to leave/mute DM conversation - [ ] Ability to leave/mute DM conversation
- [ ] Add petnames for channels - [ ] Add petnames for channels

View File

@ -142,7 +142,7 @@ const loadPeople = async (pubkeys, {relays = null, kinds = personKinds, force =
) )
} }
const loadParents = notes => { const loadParents = (notes, opts = {}) => {
const notesWithParent = notes.filter(findReplyId) const notesWithParent = notes.filter(findReplyId)
if (notesWithParent.length === 0) { if (notesWithParent.length === 0) {
@ -151,7 +151,8 @@ const loadParents = notes => {
return load({ return load({
relays: sampleRelays(aggregateScores(notesWithParent.map(getRelaysForEventParent)), 0.3), relays: sampleRelays(aggregateScores(notesWithParent.map(getRelaysForEventParent)), 0.3),
filter: {kinds: [1], ids: notesWithParent.map(findReplyId)} filter: {kinds: [1], ids: notesWithParent.map(findReplyId)},
...opts,
}) })
} }

View File

@ -1,6 +1,6 @@
import type {Person} from 'src/util/types' import type {Person} from 'src/util/types'
import type {Readable} from 'svelte/store' import type {Readable} from 'svelte/store'
import {pipe, assoc, whereEq, when, concat, reject, nth, map} from 'ramda' import {last, pipe, assoc, whereEq, when, concat, reject, nth, map} from 'ramda'
import {synced} from 'src/util/misc' import {synced} from 'src/util/misc'
import {derived} from 'svelte/store' import {derived} from 'svelte/store'
import database from 'src/agent/database' import database from 'src/agent/database'
@ -111,23 +111,23 @@ const user = {
relays, relays,
getRelays: () => relaysCopy, getRelays: () => relaysCopy,
updateRelays(f) { async updateRelays(f) {
const $relays = f(relaysCopy) const $relays = f(relaysCopy)
anonRelays.set($relays) anonRelays.set($relays)
if (profileCopy) { if (profileCopy) {
cmd.setRelays($relays, $relays) await last(cmd.setRelays($relays, $relays))
} }
}, },
async addRelay(url) { async addRelay(url) {
this.updateRelays($relays => $relays.concat({url, write: true, read: true})) await this.updateRelays($relays => $relays.concat({url, write: true, read: true}))
}, },
async removeRelay(url) { async removeRelay(url) {
this.updateRelays(reject(whereEq({url}))) await this.updateRelays(reject(whereEq({url})))
}, },
async setRelayWriteCondition(url, write) { async setRelayWriteCondition(url, write) {
this.updateRelays(map(when(whereEq({url}), assoc('write', write)))) await this.updateRelays(map(when(whereEq({url}), assoc('write', write))))
}, },
} }

View File

@ -6,5 +6,9 @@
</script> </script>
<div <div
class={cx($$props.class, `overflow-hidden w-${size} h-${size} rounded-full bg-cover bg-center shrink-0 border border-solid border-white`)} class={cx(
$$props.class,
`overflow-hidden w-${size} h-${size} rounded-full bg-cover bg-center shrink-0 border
border-solid border-white inline-block`
)}
style="background-image: url({src})" /> style="background-image: url({src})" />

View File

@ -32,12 +32,13 @@
// Remove people we're not interested in hearing about, sort by created date // Remove people we're not interested in hearing about, sort by created date
newNotes = newNotes.filter(e => !muffle.includes(e.pubkey)) newNotes = newNotes.filter(e => !muffle.includes(e.pubkey))
// Load parents before showing the notes so we have hierarchy // Load parents before showing the notes so we have hierarchy. Give it a short
// timeout, since this is really just a nice-to-have
const combined = uniqBy( const combined = uniqBy(
prop('id'), prop('id'),
newNotes newNotes
.filter(propEq('kind', 1)) .filter(propEq('kind', 1))
.concat(await network.loadParents(newNotes)) .concat(await network.loadParents(newNotes, {timeout: 500}))
.map(asDisplayEvent) .map(asDisplayEvent)
) )

View File

@ -8,6 +8,7 @@
import Toggle from "src/partials/Toggle.svelte" import Toggle from "src/partials/Toggle.svelte"
import pool from 'src/agent/pool' import pool from 'src/agent/pool'
import user from "src/agent/user" import user from "src/agent/user"
import {loadAppData} from 'src/app'
export let relay export let relay
export let theme = 'dark' export let theme = 'dark'
@ -22,6 +23,16 @@
$: joined = find(propEq('url', relay.url), $relays) $: joined = find(propEq('url', relay.url), $relays)
const removeRelay = () => user.removeRelay(relay.url)
const addRelay = async () => {
await user.addRelay(relay.url)
if (!user.getProfile()?.kind0) {
loadAppData(user.getPubkey())
}
}
onMount(() => { onMount(() => {
return poll(10_000, async () => { return poll(10_000, async () => {
const conn = await pool.getConnection(relay.url) const conn = await pool.getConnection(relay.url)
@ -67,14 +78,14 @@
{#if $relays.length > 1} {#if $relays.length > 1}
<button <button
class="flex gap-3 items-center text-light" class="flex gap-3 items-center text-light"
on:click={() => user.removeRelay(relay.url)}> on:click={removeRelay}>
<i class="fa fa-right-from-bracket" /> Leave <i class="fa fa-right-from-bracket" /> Leave
</button> </button>
{/if} {/if}
{:else} {:else}
<button <button
class="flex gap-3 items-center text-light" class="flex gap-3 items-center text-light"
on:click={() => user.addRelay(relay.url)}> on:click={addRelay}>
<i class="fa fa-right-to-bracket" /> Join <i class="fa fa-right-to-bracket" /> Join
</button> </button>
{/if} {/if}

View File

@ -6,10 +6,11 @@
import Button from 'src/partials/Button.svelte' import Button from 'src/partials/Button.svelte'
import user from 'src/agent/user' import user from 'src/agent/user'
import {toast, modal} from "src/app/ui" import {toast, modal} from "src/app/ui"
import {loadAppData} from 'src/app'
let url = $modal.url let url = $modal.url
const submit = e => { const submit = async e => {
e.preventDefault() e.preventDefault()
url = url.trim() url = url.trim()
@ -27,8 +28,13 @@
return toast.show("error", "That isn't a valid websocket url") return toast.show("error", "That isn't a valid websocket url")
} }
user.addRelay(url)
modal.set(null) modal.set(null)
await user.addRelay(url)
if (!user.getProfile()?.kind0) {
loadAppData(user.getPubkey())
}
} }
</script> </script>

View File

@ -3,14 +3,16 @@
import {onMount} from 'svelte' import {onMount} from 'svelte'
import {fly} from 'svelte/transition' import {fly} from 'svelte/transition'
import {ellipsize} from 'hurdak/lib/hurdak' import {ellipsize} from 'hurdak/lib/hurdak'
import {displayPerson} from 'src/util/nostr'
import {now, formatTimestamp, createScroller} from 'src/util/misc' import {now, formatTimestamp, createScroller} from 'src/util/misc'
import Spinner from 'src/partials/Spinner.svelte' import Spinner from 'src/partials/Spinner.svelte'
import Content from 'src/partials/Content.svelte' import Content from 'src/partials/Content.svelte'
import Badge from "src/partials/Badge.svelte" import Anchor from 'src/partials/Anchor.svelte'
import ImageCircle from "src/partials/ImageCircle.svelte"
import Alert from 'src/partials/Alert.svelte' import Alert from 'src/partials/Alert.svelte'
import database from 'src/agent/database' import database from 'src/agent/database'
import alerts from 'src/app/alerts' import alerts from 'src/app/alerts'
import {modal} from 'src/app/ui' import {modal, routes} from 'src/app/ui'
let limit = 0 let limit = 0
let notes = null let notes = null
@ -31,6 +33,7 @@
{#if notes} {#if notes}
<Content> <Content>
{#each notes as note (note.id)} {#each notes as note (note.id)}
{@const person = database.getPersonWithFallback(note.pubkey)}
<div in:fly={{y: 20}}> <div in:fly={{y: 20}}>
{#if note.replies.length > 0} {#if note.replies.length > 0}
<Alert type="replies" {note} /> <Alert type="replies" {note} />
@ -41,11 +44,12 @@
class="py-2 px-3 flex flex-col gap-2 text-white cursor-pointer transition-all w-full class="py-2 px-3 flex flex-col gap-2 text-white cursor-pointer transition-all w-full
border border-solid border-black hover:border-medium hover:bg-dark text-left" border border-solid border-black hover:border-medium hover:bg-dark text-left"
on:click={() => modal.set({type: 'note/detail', note})}> on:click={() => modal.set({type: 'note/detail', note})}>
<div class="flex gap-2 items-center justify-between relative"> <div class="flex gap-2 items-center justify-between relative w-full">
<div class="flex gap-2 items-center"> <Anchor type="unstyled" href={routes.person(person.pubkey)} class="align-middle">
<Badge person={database.getPersonWithFallback(note.pubkey)} /> <ImageCircle src={person.kind0?.picture} />
<span>mentioned you in their note.</span> <span class="text-lg font-bold ml-1">{displayPerson(person)}</span>
</div> <span>mentioned you.</span>
</Anchor>
<p class="text-sm text-light">{formatTimestamp(note.created_at)}</p> <p class="text-sm text-light">{formatTimestamp(note.created_at)}</p>
</div> </div>
<div class="ml-6 text-light"> <div class="ml-6 text-light">

View File

@ -34,7 +34,7 @@
if (note) { if (note) {
log('NoteDetail', nip19.noteEncode(note.id), note) log('NoteDetail', nip19.noteEncode(note.id), note)
await network.streamContext({ network.streamContext({
depth: 6, depth: 6,
notes: [note], notes: [note],
onChunk: context => { onChunk: context => {

View File

@ -6,7 +6,7 @@
export let pubkeys export let pubkeys
const people = database.watch('people', people => people.all({pubkey: pubkeys})) const people = database.watch('people', t => pubkeys.map(database.getPersonWithFallback))
network.loadPeople(pubkeys) network.loadPeople(pubkeys)
</script> </script>