Fix load bypassing freshness
This commit is contained in:
@@ -19,8 +19,11 @@ export const collection = <T, LoadArgs extends any[]>({
|
|||||||
const pending = new Map<string, Promise<Maybe<T>>>()
|
const pending = new Map<string, Promise<Maybe<T>>>()
|
||||||
|
|
||||||
const loadItem = async (key: string, ...args: LoadArgs) => {
|
const loadItem = async (key: string, ...args: LoadArgs) => {
|
||||||
if (getFreshness(name, key) > now() - 3600) {
|
const item = indexStore.get().get(key)
|
||||||
return indexStore.get().get(key)
|
const delta = item ? 3600 : 300
|
||||||
|
|
||||||
|
if (getFreshness(name, key) > now() - delta) {
|
||||||
|
return item
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pending.has(key)) {
|
if (pending.has(key)) {
|
||||||
@@ -47,7 +50,7 @@ export const collection = <T, LoadArgs extends any[]>({
|
|||||||
|
|
||||||
// If we don't yet have the item, or it's stale, trigger a request for it. The derived
|
// If we don't yet have the item, or it's stale, trigger a request for it. The derived
|
||||||
// store will update when it arrives
|
// store will update when it arrives
|
||||||
load(key, ...args)
|
loadItem(key, ...args)
|
||||||
|
|
||||||
return derived(indexStore, $index => $index.get(key))
|
return derived(indexStore, $index => $index.get(key))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import {first} from "@welshman/lib"
|
|
||||||
import {Repository, Relay} from "@welshman/util"
|
import {Repository, Relay} from "@welshman/util"
|
||||||
import type {TrustedEvent} from "@welshman/util"
|
import type {TrustedEvent} from "@welshman/util"
|
||||||
import {Tracker, subscribe as baseSubscribe} from "@welshman/net"
|
import {Tracker, subscribe as baseSubscribe} from "@welshman/net"
|
||||||
@@ -6,9 +5,11 @@ import type {SubscribeRequest} from "@welshman/net"
|
|||||||
import {createEventStore} from "@welshman/store"
|
import {createEventStore} from "@welshman/store"
|
||||||
|
|
||||||
export const env: {
|
export const env: {
|
||||||
|
BOOTSTRAP_RELAYS: string[]
|
||||||
DUFFLEPUD_URL?: string
|
DUFFLEPUD_URL?: string
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
} = {
|
} = {
|
||||||
|
BOOTSTRAP_RELAYS: [],
|
||||||
DUFFLEPUD_URL: undefined,
|
DUFFLEPUD_URL: undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,4 +40,16 @@ export const load = (request: SubscribeRequest) =>
|
|||||||
sub.emitter.on("complete", () => resolve(events))
|
sub.emitter.on("complete", () => resolve(events))
|
||||||
})
|
})
|
||||||
|
|
||||||
export const loadOne = async (request: SubscribeRequest) => first(await load(request))
|
export const loadOne = (request: SubscribeRequest) =>
|
||||||
|
new Promise<TrustedEvent | null>(resolve => {
|
||||||
|
const sub = subscribe({closeOnEose: true, timeout: 3000, ...request})
|
||||||
|
|
||||||
|
sub.emitter.on("event", (url: string, event: TrustedEvent) => {
|
||||||
|
resolve(event)
|
||||||
|
sub.close()
|
||||||
|
})
|
||||||
|
|
||||||
|
sub.emitter.on("complete", () => {
|
||||||
|
resolve(null)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {deriveEventsMapped, withGetter} from '@welshman/store'
|
|||||||
import {repository, load} from './core'
|
import {repository, load} from './core'
|
||||||
import {collection} from './collection'
|
import {collection} from './collection'
|
||||||
import {ensurePlaintext} from './plaintext'
|
import {ensurePlaintext} from './plaintext'
|
||||||
import {getWriteRelayUrls, loadRelaySelections} from './relaySelections'
|
import {getHintsForPubkey} from './relaySelections'
|
||||||
|
|
||||||
export const follows = withGetter(
|
export const follows = withGetter(
|
||||||
deriveEventsMapped<PublishedList>(repository, {
|
deriveEventsMapped<PublishedList>(repository, {
|
||||||
@@ -28,13 +28,10 @@ export const {
|
|||||||
name: "follows",
|
name: "follows",
|
||||||
store: follows,
|
store: follows,
|
||||||
getKey: follows => follows.event.pubkey,
|
getKey: follows => follows.event.pubkey,
|
||||||
load: async (pubkey: string, hints = [], request: Partial<SubscribeRequest> = {}) => {
|
load: async (pubkey: string, request: Partial<SubscribeRequest> = {}) =>
|
||||||
const relays = getWriteRelayUrls(await loadRelaySelections(pubkey, hints))
|
load({
|
||||||
|
|
||||||
return load({
|
|
||||||
...request,
|
...request,
|
||||||
relays: [...relays, ...hints],
|
|
||||||
filters: [{kinds: [FOLLOWS], authors: [pubkey]}],
|
filters: [{kinds: [FOLLOWS], authors: [pubkey]}],
|
||||||
})
|
relays: await getHintsForPubkey(pubkey, request.relays || []),
|
||||||
},
|
}),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import {writable, derived} from 'svelte/store'
|
import {writable} from 'svelte/store'
|
||||||
import {withGetter} from '@welshman/store'
|
import {withGetter} from '@welshman/store'
|
||||||
import {uniq, indexBy, uniqBy, batcher, postJson, last} from '@welshman/lib'
|
import {uniq, uniqBy, batcher, postJson, last} from '@welshman/lib'
|
||||||
import {env} from './core'
|
import {env} from './core'
|
||||||
import {collection} from './collection'
|
import {collection} from './collection'
|
||||||
import {profilesByPubkey} from './profiles'
|
|
||||||
|
|
||||||
export type Handle = {
|
export type Handle = {
|
||||||
nip05: string
|
nip05: string
|
||||||
@@ -14,13 +13,6 @@ export type Handle = {
|
|||||||
|
|
||||||
export const handles = withGetter(writable<Handle[]>([]))
|
export const handles = withGetter(writable<Handle[]>([]))
|
||||||
|
|
||||||
export const handlesByPubkey = derived([profilesByPubkey, handles], ([$profilesByPubkey, $handles]) =>
|
|
||||||
indexBy(
|
|
||||||
$handle => $handle.pubkey,
|
|
||||||
$handles.filter($handle => $handle.pubkey && $profilesByPubkey.get($handle.pubkey)?.nip05 === $handle.nip05),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
export const fetchHandles = (handles: string[]) => {
|
export const fetchHandles = (handles: string[]) => {
|
||||||
const base = env.DUFFLEPUD_URL!
|
const base = env.DUFFLEPUD_URL!
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {deriveEventsMapped, withGetter} from '@welshman/store'
|
|||||||
import {repository, load} from './core'
|
import {repository, load} from './core'
|
||||||
import {collection} from './collection'
|
import {collection} from './collection'
|
||||||
import {ensurePlaintext} from './plaintext'
|
import {ensurePlaintext} from './plaintext'
|
||||||
import {getWriteRelayUrls, loadRelaySelections} from './relaySelections'
|
import {getHintsForPubkey} from './relaySelections'
|
||||||
|
|
||||||
export const mutes = withGetter(
|
export const mutes = withGetter(
|
||||||
deriveEventsMapped<PublishedList>(repository, {
|
deriveEventsMapped<PublishedList>(repository, {
|
||||||
@@ -28,13 +28,10 @@ export const {
|
|||||||
name: "mutes",
|
name: "mutes",
|
||||||
store: mutes,
|
store: mutes,
|
||||||
getKey: mute => mute.event.pubkey,
|
getKey: mute => mute.event.pubkey,
|
||||||
load: async (pubkey: string, hints = [], request: Partial<SubscribeRequest> = {}) => {
|
load: async (pubkey: string, request: Partial<SubscribeRequest> = {}) =>
|
||||||
const relays = getWriteRelayUrls(await loadRelaySelections(pubkey, hints))
|
load({
|
||||||
|
|
||||||
return load({
|
|
||||||
...request,
|
...request,
|
||||||
relays: [...relays, ...hints],
|
|
||||||
filters: [{kinds: [MUTES], authors: [pubkey]}],
|
filters: [{kinds: [MUTES], authors: [pubkey]}],
|
||||||
})
|
relays: await getHintsForPubkey(pubkey, request.relays || []),
|
||||||
},
|
}),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,17 +2,19 @@ import {derived} from 'svelte/store'
|
|||||||
import {readProfile, displayProfile, displayPubkey, PROFILE} from '@welshman/util'
|
import {readProfile, displayProfile, displayPubkey, PROFILE} from '@welshman/util'
|
||||||
import {type SubscribeRequest} from "@welshman/net"
|
import {type SubscribeRequest} from "@welshman/net"
|
||||||
import {type PublishedProfile} from "@welshman/util"
|
import {type PublishedProfile} from "@welshman/util"
|
||||||
import {deriveEventsMapped} from '@welshman/store'
|
import {deriveEventsMapped, withGetter} from '@welshman/store'
|
||||||
import {repository, load} from './core'
|
import {repository, load} from './core'
|
||||||
import {createSearch} from './util'
|
import {createSearch} from './util'
|
||||||
import {collection} from './collection'
|
import {collection} from './collection'
|
||||||
import {getWriteRelayUrls, loadRelaySelections} from './relaySelections'
|
import {getHintsForPubkey} from './relaySelections'
|
||||||
|
|
||||||
export const profiles = deriveEventsMapped<PublishedProfile>(repository, {
|
export const profiles = withGetter(
|
||||||
filters: [{kinds: [PROFILE]}],
|
deriveEventsMapped<PublishedProfile>(repository, {
|
||||||
eventToItem: readProfile,
|
filters: [{kinds: [PROFILE]}],
|
||||||
itemToEvent: item => item.event,
|
eventToItem: readProfile,
|
||||||
})
|
itemToEvent: item => item.event,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
indexStore: profilesByPubkey,
|
indexStore: profilesByPubkey,
|
||||||
@@ -22,15 +24,12 @@ export const {
|
|||||||
name: "profiles",
|
name: "profiles",
|
||||||
store: profiles,
|
store: profiles,
|
||||||
getKey: profile => profile.event.pubkey,
|
getKey: profile => profile.event.pubkey,
|
||||||
load: async (pubkey: string, hints = [], request: Partial<SubscribeRequest> = {}) => {
|
load: async (pubkey: string, request: Partial<SubscribeRequest> = {}) =>
|
||||||
const relays = getWriteRelayUrls(await loadRelaySelections(pubkey, hints))
|
load({
|
||||||
|
|
||||||
return load({
|
|
||||||
...request,
|
...request,
|
||||||
relays: [...relays, ...hints],
|
|
||||||
filters: [{kinds: [PROFILE], authors: [pubkey]}],
|
filters: [{kinds: [PROFILE], authors: [pubkey]}],
|
||||||
})
|
relays: await getHintsForPubkey(pubkey, request.relays || []),
|
||||||
},
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const profileSearch = derived(profiles, $profiles =>
|
export const profileSearch = derived(profiles, $profiles =>
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
import {RELAYS, getRelayTags, normalizeRelayUrl, type TrustedEvent} from '@welshman/util'
|
import {uniq} from '@welshman/lib'
|
||||||
|
import {INBOX_RELAYS, RELAYS, getRelayTags, normalizeRelayUrl, type TrustedEvent} from '@welshman/util'
|
||||||
import {type SubscribeRequest} from "@welshman/net"
|
import {type SubscribeRequest} from "@welshman/net"
|
||||||
import {deriveEvents} from '@welshman/store'
|
import {deriveEvents, withGetter} from '@welshman/store'
|
||||||
import {load, repository} from './core'
|
import {env, load, repository} from './core'
|
||||||
import {collection} from './collection'
|
import {collection} from './collection'
|
||||||
|
|
||||||
|
export const getRelayUrls = (event?: TrustedEvent): string[] =>
|
||||||
|
getRelayTags(event?.tags || [])
|
||||||
|
.map((t: string[]) => normalizeRelayUrl(t[1]))
|
||||||
|
|
||||||
export const getReadRelayUrls = (event?: TrustedEvent): string[] =>
|
export const getReadRelayUrls = (event?: TrustedEvent): string[] =>
|
||||||
getRelayTags(event?.tags || [])
|
getRelayTags(event?.tags || [])
|
||||||
.filter((t: string[]) => !t[2] || t[2] === "read")
|
.filter((t: string[]) => !t[2] || t[2] === "read")
|
||||||
@@ -14,7 +19,7 @@ export const getWriteRelayUrls = (event?: TrustedEvent): string[] =>
|
|||||||
.filter((t: string[]) => !t[2] || t[2] === "write")
|
.filter((t: string[]) => !t[2] || t[2] === "write")
|
||||||
.map((t: string[]) => normalizeRelayUrl(t[1]))
|
.map((t: string[]) => normalizeRelayUrl(t[1]))
|
||||||
|
|
||||||
export const relaySelections = deriveEvents(repository, {filters: [{kinds: [RELAYS]}]})
|
export const relaySelections = withGetter(deriveEvents(repository, {filters: [{kinds: [RELAYS]}]}))
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
indexStore: relaySelectionsByPubkey,
|
indexStore: relaySelectionsByPubkey,
|
||||||
@@ -24,10 +29,31 @@ export const {
|
|||||||
name: "relaySelections",
|
name: "relaySelections",
|
||||||
store: relaySelections,
|
store: relaySelections,
|
||||||
getKey: relaySelections => relaySelections.pubkey,
|
getKey: relaySelections => relaySelections.pubkey,
|
||||||
load: (pubkey: string, relays: string[], request: Partial<SubscribeRequest> = {}) =>
|
load: (pubkey: string, request: Partial<SubscribeRequest> = {}) =>
|
||||||
load({
|
load({
|
||||||
...request,
|
...request,
|
||||||
relays,
|
|
||||||
filters: [{kinds: [RELAYS], authors: [pubkey]}],
|
filters: [{kinds: [RELAYS], authors: [pubkey]}],
|
||||||
|
relays: [...env.BOOTSTRAP_RELAYS, ...request.relays || []],
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const getHintsForPubkey = async (pubkey: string, relays: string[] = []) =>
|
||||||
|
uniq([...relays, ...env.BOOTSTRAP_RELAYS, ...getWriteRelayUrls(await loadRelaySelections(pubkey, {relays}))])
|
||||||
|
|
||||||
|
export const inboxRelaySelections = withGetter(deriveEvents(repository, {filters: [{kinds: [RELAYS]}]}))
|
||||||
|
|
||||||
|
export const {
|
||||||
|
indexStore: inboxRelaySelectionsByPubkey,
|
||||||
|
deriveItem: deriveInboxRelaySelections,
|
||||||
|
loadItem: loadInboxRelaySelections,
|
||||||
|
} = collection({
|
||||||
|
name: "inboxRelaySelections",
|
||||||
|
store: inboxRelaySelections,
|
||||||
|
getKey: inboxRelaySelections => inboxRelaySelections.pubkey,
|
||||||
|
load: async (pubkey: string, request: Partial<SubscribeRequest> = {}) =>
|
||||||
|
load({
|
||||||
|
...request,
|
||||||
|
filters: [{kinds: [INBOX_RELAYS], authors: [pubkey]}],
|
||||||
|
relays: await getHintsForPubkey(pubkey, request.relays),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,20 +1,12 @@
|
|||||||
import {writable, derived} from 'svelte/store'
|
import {writable} from 'svelte/store'
|
||||||
import {withGetter} from '@welshman/store'
|
import {withGetter} from '@welshman/store'
|
||||||
import type {Zapper} from '@welshman/util'
|
import type {Zapper} from '@welshman/util'
|
||||||
import {uniq, identity, bech32ToHex, indexBy, tryCatch, uniqBy, batcher, postJson} from '@welshman/lib'
|
import {uniq, identity, bech32ToHex, tryCatch, uniqBy, batcher, postJson} from '@welshman/lib'
|
||||||
import {env} from './core'
|
import {env} from './core'
|
||||||
import {collection} from './collection'
|
import {collection} from './collection'
|
||||||
import {profilesByPubkey} from './profiles'
|
|
||||||
|
|
||||||
export const zappers = withGetter(writable<Zapper[]>([]))
|
export const zappers = withGetter(writable<Zapper[]>([]))
|
||||||
|
|
||||||
export const zappersByPubkey = derived([profilesByPubkey, zappers], ([$profilesByPubkey, $zappers]) =>
|
|
||||||
indexBy(
|
|
||||||
$zapper => $zapper.pubkey,
|
|
||||||
$zappers.filter($zapper => $zapper.pubkey && $profilesByPubkey.get($zapper.pubkey)?.lnurl === $zapper.lnurl),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
export const fetchZappers = (lnurls: string[]) => {
|
export const fetchZappers = (lnurls: string[]) => {
|
||||||
const base = env.DUFFLEPUD_URL!
|
const base = env.DUFFLEPUD_URL!
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user