Browse Source

bug-fixes

imwald
Silberengel 4 weeks ago
parent
commit
69ff3a1a42
  1. 1
      src/components/NoteList/index.tsx
  2. 17
      src/hooks/useProfileAuthorFeedSubRequests.ts
  3. 4
      src/lib/favorites-feed-relays.ts
  4. 9
      src/lib/relay-strikes.ts
  5. 11
      src/services/client.service.ts

1
src/components/NoteList/index.tsx

@ -3151,6 +3151,7 @@ const NoteList = forwardRef(
needSort: !areAlgoRelays, needSort: !areAlgoRelays,
firstRelayResultGraceMs: FIRST_RELAY_RESULT_GRACE_MS, firstRelayResultGraceMs: FIRST_RELAY_RESULT_GRACE_MS,
relayAuthoritativeTimeline: relayAuthoritativeFeedOnlyRef.current, relayAuthoritativeTimeline: relayAuthoritativeFeedOnlyRef.current,
connectionSlotPriority: isProfileTimelineFeed,
onRelaySubscribeWaveComplete: (rows) => { onRelaySubscribeWaveComplete: (rows) => {
if (!effectActive) return if (!effectActive) return
setFeedSubscribeRelayOutcomes(rows) setFeedSubscribeRelayOutcomes(rows)

17
src/hooks/useProfileAuthorFeedSubRequests.ts

@ -16,6 +16,14 @@ function relayListsContentKey(favoriteRelays: string[], blockedRelays: string[])
return `${fav}\u0000${blk}` return `${fav}\u0000${blk}`
} }
function relayUrlListKey(urls: readonly string[]): string {
return [...urls]
.map((u) => normalizeAnyRelayUrl(u) || u)
.filter(Boolean)
.sort()
.join('\u0001')
}
const emptyAuthor = { const emptyAuthor = {
read: [] as string[], read: [] as string[],
write: [] as string[], write: [] as string[],
@ -73,10 +81,12 @@ export function useProfileAuthorFeedSubRequests({
/** Single emission per visit: provisional→full relay stacks used to restart NoteList and wipe rows mid-fetch. */ /** Single emission per visit: provisional→full relay stacks used to restart NoteList and wipe rows mid-fetch. */
const [relayUrls, setRelayUrls] = useState<string[] | null>(null) const [relayUrls, setRelayUrls] = useState<string[] | null>(null)
const relayUrlsPubkeyRef = useRef<string | null>(null) const relayUrlsPubkeyRef = useRef<string | null>(null)
const appliedRelayUrlsKeyRef = useRef('')
useEffect(() => { useEffect(() => {
if (relayUrlsPubkeyRef.current !== pubkey) { if (relayUrlsPubkeyRef.current !== pubkey) {
relayUrlsPubkeyRef.current = pubkey relayUrlsPubkeyRef.current = pubkey
appliedRelayUrlsKeyRef.current = ''
setRelayUrls(null) setRelayUrls(null)
} }
}, [pubkey]) }, [pubkey])
@ -95,10 +105,12 @@ export function useProfileAuthorFeedSubRequests({
kinds, kinds,
useGlobalRelayBootstrap useGlobalRelayBootstrap
) )
if (urls.length > 0) { if (urls.length === 0) return
const key = relayUrlListKey(urls)
if (key === appliedRelayUrlsKeyRef.current) return
appliedRelayUrlsKeyRef.current = key
setRelayUrls(urls) setRelayUrls(urls)
} }
}
// Bootstrap immediately (favorites + fast-read) so /users/… feeds are not stuck on "Nothing to load" // Bootstrap immediately (favorites + fast-read) so /users/… feeds are not stuck on "Nothing to load"
// while fetchRelayList runs (often 10–30s under relay contention). // while fetchRelayList runs (often 10–30s under relay contention).
@ -137,6 +149,7 @@ export function useProfileAuthorFeedSubRequests({
}, [authorHex, kindsKey, limit]) }, [authorHex, kindsKey, limit])
const refresh = useCallback(() => { const refresh = useCallback(() => {
appliedRelayUrlsKeyRef.current = ''
setRelayUrls(null) setRelayUrls(null)
setRefreshToken((n) => n + 1) setRefreshToken((n) => n + 1)
}, []) }, [])

4
src/lib/favorites-feed-relays.ts

@ -17,6 +17,7 @@ import {
} from '@/lib/relay-url-priority' } from '@/lib/relay-url-priority'
import { feedRelayPolicyUrls, type FeedRelayLayer } from '@/features/feed/relay-policy' import { feedRelayPolicyUrls, type FeedRelayLayer } from '@/features/feed/relay-policy'
import { stripMailboxLocalUrlsForRemoteViewers } from '@/lib/relay-list-sanitize' import { stripMailboxLocalUrlsForRemoteViewers } from '@/lib/relay-list-sanitize'
import { relaySessionStrikes } from '@/lib/relay-strikes'
import { profileFetchRelayUrlsWithoutFastReadLayer } from '@/lib/viewer-relay-defaults' import { profileFetchRelayUrlsWithoutFastReadLayer } from '@/lib/viewer-relay-defaults'
const blockedSet = (blockedRelays: string[]) => const blockedSet = (blockedRelays: string[]) =>
@ -258,9 +259,10 @@ export function buildProfilePageReadRelayUrls(
? pinFastReadForRemoteProfileFeed(merged, fastReadLayer, blockedRelays, cap) ? pinFastReadForRemoteProfileFeed(merged, fastReadLayer, blockedRelays, cap)
: merged : merged
} }
return pinFastReadForRemote const merged = pinFastReadForRemote
? pinFastReadForRemoteProfileFeed(urls, fastReadLayer, blockedRelays, maxRelays) ? pinFastReadForRemoteProfileFeed(urls, fastReadLayer, blockedRelays, maxRelays)
: urls : urls
return relaySessionStrikes.filterReadHttpUrls(merged)
} }
/** /**

9
src/lib/relay-strikes.ts

@ -175,7 +175,14 @@ class RelaySessionStrikes {
if (!this.cacheRelayKeys.has(key)) { if (!this.cacheRelayKeys.has(key)) {
// HTTP index failures often arrive in parallel; count each so session skip engages quickly. // HTTP index failures often arrive in parallel; count each so session skip engages quickly.
if (_source !== 'http' && now - e.readLastStrikeIncrementAt < STRIKE_INCREMENT_DEBOUNCE_MS) return // Connection refused / unreachable: do not debounce — profile feeds open many relays at once.
if (
_source !== 'http' &&
_source !== 'connection' &&
now - e.readLastStrikeIncrementAt < STRIKE_INCREMENT_DEBOUNCE_MS
) {
return
}
e.readLastStrikeIncrementAt = now e.readLastStrikeIncrementAt = now
} }

11
src/services/client.service.ts

@ -2210,7 +2210,8 @@ class ClientService extends EventTarget {
needSort = true, needSort = true,
firstRelayResultGraceMs = FIRST_RELAY_RESULT_GRACE_MS, firstRelayResultGraceMs = FIRST_RELAY_RESULT_GRACE_MS,
onRelaySubscribeWaveComplete, onRelaySubscribeWaveComplete,
relayAuthoritativeTimeline = false relayAuthoritativeTimeline = false,
connectionSlotPriority = false
}: { }: {
startLogin?: () => void startLogin?: () => void
needSort?: boolean needSort?: boolean
@ -2223,6 +2224,8 @@ class ClientService extends EventTarget {
* skip persisting this shard, and do not widen an empty shard to {@link FAST_READ_RELAY_URLS}. * skip persisting this shard, and do not widen an empty shard to {@link FAST_READ_RELAY_URLS}.
*/ */
relayAuthoritativeTimeline?: boolean relayAuthoritativeTimeline?: boolean
/** Jump the global {@link QueryService.acquireGlobalRelayConnectionSlot} queue (profile timelines). */
connectionSlotPriority?: boolean
} = {} } = {}
) { ) {
const timelineBatchId = `tl-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 9)}` const timelineBatchId = `tl-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 9)}`
@ -2366,6 +2369,7 @@ class ClientService extends EventTarget {
needSort, needSort,
firstRelayResultGraceMs, firstRelayResultGraceMs,
relayAuthoritativeTimeline, relayAuthoritativeTimeline,
connectionSlotPriority,
relayReqLog: { relayReqLog: {
groupId: `${timelineBatchId}:shard${shardIndex}`, groupId: `${timelineBatchId}:shard${shardIndex}`,
onBatchEnd: onShardSubscribeBatchEnd onBatchEnd: onShardSubscribeBatchEnd
@ -2870,6 +2874,8 @@ class ClientService extends EventTarget {
relayReqLog?: { groupId: string; onBatchEnd?: (rows: RelayOpTerminalRow[]) => void }, relayReqLog?: { groupId: string; onBatchEnd?: (rows: RelayOpTerminalRow[]) => void },
/** See {@link ClientService.subscribeTimeline} third-arg `relayAuthoritativeTimeline`. */ /** See {@link ClientService.subscribeTimeline} third-arg `relayAuthoritativeTimeline`. */
relayAuthoritativeTimeline?: boolean relayAuthoritativeTimeline?: boolean
/** See {@link ClientService.subscribeTimeline} third-arg `connectionSlotPriority`. */
connectionSlotPriority?: boolean
} = {} } = {}
) { ) {
let relays = Array.from(new Set(urls)) let relays = Array.from(new Set(urls))
@ -3185,7 +3191,8 @@ class ClientService extends EventTarget {
oneose: httpOnlyShard ? undefined : handleTimelineEose, oneose: httpOnlyShard ? undefined : handleTimelineEose,
onclose: onClose, onclose: onClose,
connectionSlotPriority: connectionSlotPriority:
relayAuthoritativeTimeline && wsRelays.length === 1 && navigator.onLine connectionSlotPriority === true ||
(relayAuthoritativeTimeline && wsRelays.length === 1 && navigator.onLine)
}, },
httpOnlyShard ? undefined : relayReqLog) httpOnlyShard ? undefined : relayReqLog)

Loading…
Cancel
Save