From 69ff3a1a423348761715918aa78dd3bad98eafa8 Mon Sep 17 00:00:00 2001 From: Silberengel Date: Wed, 20 May 2026 20:12:20 +0200 Subject: [PATCH] bug-fixes --- src/components/NoteList/index.tsx | 1 + src/hooks/useProfileAuthorFeedSubRequests.ts | 19 ++++++++++++++++--- src/lib/favorites-feed-relays.ts | 4 +++- src/lib/relay-strikes.ts | 9 ++++++++- src/services/client.service.ts | 11 +++++++++-- 5 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/components/NoteList/index.tsx b/src/components/NoteList/index.tsx index af0a0fa5..1b63e4f9 100644 --- a/src/components/NoteList/index.tsx +++ b/src/components/NoteList/index.tsx @@ -3151,6 +3151,7 @@ const NoteList = forwardRef( needSort: !areAlgoRelays, firstRelayResultGraceMs: FIRST_RELAY_RESULT_GRACE_MS, relayAuthoritativeTimeline: relayAuthoritativeFeedOnlyRef.current, + connectionSlotPriority: isProfileTimelineFeed, onRelaySubscribeWaveComplete: (rows) => { if (!effectActive) return setFeedSubscribeRelayOutcomes(rows) diff --git a/src/hooks/useProfileAuthorFeedSubRequests.ts b/src/hooks/useProfileAuthorFeedSubRequests.ts index 3ddbf58c..1ea74fa3 100644 --- a/src/hooks/useProfileAuthorFeedSubRequests.ts +++ b/src/hooks/useProfileAuthorFeedSubRequests.ts @@ -16,6 +16,14 @@ function relayListsContentKey(favoriteRelays: string[], blockedRelays: string[]) return `${fav}\u0000${blk}` } +function relayUrlListKey(urls: readonly string[]): string { + return [...urls] + .map((u) => normalizeAnyRelayUrl(u) || u) + .filter(Boolean) + .sort() + .join('\u0001') +} + const emptyAuthor = { read: [] 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. */ const [relayUrls, setRelayUrls] = useState(null) const relayUrlsPubkeyRef = useRef(null) + const appliedRelayUrlsKeyRef = useRef('') useEffect(() => { if (relayUrlsPubkeyRef.current !== pubkey) { relayUrlsPubkeyRef.current = pubkey + appliedRelayUrlsKeyRef.current = '' setRelayUrls(null) } }, [pubkey]) @@ -95,9 +105,11 @@ export function useProfileAuthorFeedSubRequests({ kinds, useGlobalRelayBootstrap ) - if (urls.length > 0) { - setRelayUrls(urls) - } + if (urls.length === 0) return + const key = relayUrlListKey(urls) + if (key === appliedRelayUrlsKeyRef.current) return + appliedRelayUrlsKeyRef.current = key + setRelayUrls(urls) } // Bootstrap immediately (favorites + fast-read) so /users/… feeds are not stuck on "Nothing to load" @@ -137,6 +149,7 @@ export function useProfileAuthorFeedSubRequests({ }, [authorHex, kindsKey, limit]) const refresh = useCallback(() => { + appliedRelayUrlsKeyRef.current = '' setRelayUrls(null) setRefreshToken((n) => n + 1) }, []) diff --git a/src/lib/favorites-feed-relays.ts b/src/lib/favorites-feed-relays.ts index a1af85e3..5c80fa48 100644 --- a/src/lib/favorites-feed-relays.ts +++ b/src/lib/favorites-feed-relays.ts @@ -17,6 +17,7 @@ import { } from '@/lib/relay-url-priority' import { feedRelayPolicyUrls, type FeedRelayLayer } from '@/features/feed/relay-policy' import { stripMailboxLocalUrlsForRemoteViewers } from '@/lib/relay-list-sanitize' +import { relaySessionStrikes } from '@/lib/relay-strikes' import { profileFetchRelayUrlsWithoutFastReadLayer } from '@/lib/viewer-relay-defaults' const blockedSet = (blockedRelays: string[]) => @@ -258,9 +259,10 @@ export function buildProfilePageReadRelayUrls( ? pinFastReadForRemoteProfileFeed(merged, fastReadLayer, blockedRelays, cap) : merged } - return pinFastReadForRemote + const merged = pinFastReadForRemote ? pinFastReadForRemoteProfileFeed(urls, fastReadLayer, blockedRelays, maxRelays) : urls + return relaySessionStrikes.filterReadHttpUrls(merged) } /** diff --git a/src/lib/relay-strikes.ts b/src/lib/relay-strikes.ts index e287ea3e..ae7b3cb2 100644 --- a/src/lib/relay-strikes.ts +++ b/src/lib/relay-strikes.ts @@ -175,7 +175,14 @@ class RelaySessionStrikes { if (!this.cacheRelayKeys.has(key)) { // 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 } diff --git a/src/services/client.service.ts b/src/services/client.service.ts index 76242839..1554e884 100644 --- a/src/services/client.service.ts +++ b/src/services/client.service.ts @@ -2210,7 +2210,8 @@ class ClientService extends EventTarget { needSort = true, firstRelayResultGraceMs = FIRST_RELAY_RESULT_GRACE_MS, onRelaySubscribeWaveComplete, - relayAuthoritativeTimeline = false + relayAuthoritativeTimeline = false, + connectionSlotPriority = false }: { startLogin?: () => void 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}. */ 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)}` @@ -2366,6 +2369,7 @@ class ClientService extends EventTarget { needSort, firstRelayResultGraceMs, relayAuthoritativeTimeline, + connectionSlotPriority, relayReqLog: { groupId: `${timelineBatchId}:shard${shardIndex}`, onBatchEnd: onShardSubscribeBatchEnd @@ -2870,6 +2874,8 @@ class ClientService extends EventTarget { relayReqLog?: { groupId: string; onBatchEnd?: (rows: RelayOpTerminalRow[]) => void }, /** See {@link ClientService.subscribeTimeline} third-arg `relayAuthoritativeTimeline`. */ relayAuthoritativeTimeline?: boolean + /** See {@link ClientService.subscribeTimeline} third-arg `connectionSlotPriority`. */ + connectionSlotPriority?: boolean } = {} ) { let relays = Array.from(new Set(urls)) @@ -3185,7 +3191,8 @@ class ClientService extends EventTarget { oneose: httpOnlyShard ? undefined : handleTimelineEose, onclose: onClose, connectionSlotPriority: - relayAuthoritativeTimeline && wsRelays.length === 1 && navigator.onLine + connectionSlotPriority === true || + (relayAuthoritativeTimeline && wsRelays.length === 1 && navigator.onLine) }, httpOnlyShard ? undefined : relayReqLog)