Browse Source

fix relay connections and implement more-detailed logging

imwald
Silberengel 5 months ago
parent
commit
2027057832
  1. 32
      src/components/NotificationList/index.tsx
  2. 29
      src/providers/NotificationProvider.tsx
  3. 10
      src/services/client.service.ts

32
src/components/NotificationList/index.tsx

@ -1,9 +1,10 @@
import { BIG_RELAY_URLS, ExtendedKind, NOTIFICATION_LIST_STYLE } from '@/constants' import { ExtendedKind, NOTIFICATION_LIST_STYLE, FAST_READ_RELAY_URLS } from '@/constants'
import { compareEvents } from '@/lib/event' import { compareEvents } from '@/lib/event'
import { usePrimaryPage } from '@/PageManager' import { usePrimaryPage } from '@/PageManager'
import { useNostr } from '@/providers/NostrProvider' import { useNostr } from '@/providers/NostrProvider'
import { useNotification } from '@/providers/NotificationProvider' import { useNotification } from '@/providers/NotificationProvider'
import { useUserPreferences } from '@/providers/UserPreferencesProvider' import { useUserPreferences } from '@/providers/UserPreferencesProvider'
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
import client from '@/services/client.service' import client from '@/services/client.service'
import noteStatsService from '@/services/note-stats.service' import noteStatsService from '@/services/note-stats.service'
import { TNotificationType } from '@/types' import { TNotificationType } from '@/types'
@ -33,9 +34,10 @@ const NotificationList = forwardRef((_, ref) => {
const { t } = useTranslation() const { t } = useTranslation()
const { current, display } = usePrimaryPage() const { current, display } = usePrimaryPage()
const active = useMemo(() => current === 'notifications' && display, [current, display]) const active = useMemo(() => current === 'notifications' && display, [current, display])
const { pubkey } = useNostr() const { pubkey, relayList } = useNostr()
const { getNotificationsSeenAt } = useNotification() const { getNotificationsSeenAt } = useNotification()
const { notificationListStyle } = useUserPreferences() const { notificationListStyle } = useUserPreferences()
const { favoriteRelays } = useFavoriteRelays()
const [notificationType, setNotificationType] = useState<TNotificationType>('all') const [notificationType, setNotificationType] = useState<TNotificationType>('all')
const [lastReadTime, setLastReadTime] = useState(0) const [lastReadTime, setLastReadTime] = useState(0)
const [refreshCount, setRefreshCount] = useState(0) const [refreshCount, setRefreshCount] = useState(0)
@ -121,7 +123,27 @@ const NotificationList = forwardRef((_, ref) => {
setNotifications([]) setNotifications([])
setShowCount(SHOW_COUNT) setShowCount(SHOW_COUNT)
setLastReadTime(getNotificationsSeenAt()) setLastReadTime(getNotificationsSeenAt())
const relayList = await client.fetchRelayList(pubkey) // Use proper fallback hierarchy: user's read/inbox relays → favorite relays → fast read relays
const userRelayList = relayList || { read: [], write: [] }
const userReadRelays = userRelayList.read || []
const userFavoriteRelays = favoriteRelays || []
// Build relay list with proper fallback hierarchy
let primaryRelays: string[] = []
if (userReadRelays.length > 0) {
// Priority 1: User's read/inbox relays (kind 10002)
primaryRelays = userReadRelays.slice(0, 5)
console.debug('[NotificationList] Using user read relays:', primaryRelays.length, 'relays')
} else if (userFavoriteRelays.length > 0) {
// Priority 2: User's favorite relays (kind 10012)
primaryRelays = userFavoriteRelays.slice(0, 5)
console.debug('[NotificationList] Using user favorite relays:', primaryRelays.length, 'relays')
} else {
// Priority 3: Fast read relays (reliable defaults)
primaryRelays = FAST_READ_RELAY_URLS.slice(0, 5)
console.debug('[NotificationList] Using fast read relays fallback:', primaryRelays.length, 'relays')
}
// Create separate subscriptions for different notification types // Create separate subscriptions for different notification types
const subscriptions = [] const subscriptions = []
@ -130,7 +152,7 @@ const NotificationList = forwardRef((_, ref) => {
const mentionKinds = filterKinds.filter(kind => kind !== 11) const mentionKinds = filterKinds.filter(kind => kind !== 11)
if (mentionKinds.length > 0) { if (mentionKinds.length > 0) {
subscriptions.push({ subscriptions.push({
urls: relayList.read.length > 0 ? relayList.read.slice(0, 5) : BIG_RELAY_URLS, urls: primaryRelays,
filter: { filter: {
'#p': [pubkey], '#p': [pubkey],
kinds: mentionKinds, kinds: mentionKinds,
@ -142,7 +164,7 @@ const NotificationList = forwardRef((_, ref) => {
// Separate subscription for discussion notifications (kind 11) - no p-tag requirement // Separate subscription for discussion notifications (kind 11) - no p-tag requirement
if (filterKinds.includes(11)) { if (filterKinds.includes(11)) {
subscriptions.push({ subscriptions.push({
urls: relayList.read.length > 0 ? relayList.read.slice(0, 5) : BIG_RELAY_URLS, urls: primaryRelays,
filter: { filter: {
kinds: [11], kinds: [11],
limit: LIMIT limit: LIMIT

29
src/providers/NotificationProvider.tsx

@ -1,7 +1,8 @@
import { BIG_RELAY_URLS, ExtendedKind } from '@/constants' import { ExtendedKind, FAST_READ_RELAY_URLS } from '@/constants'
import { compareEvents } from '@/lib/event' import { compareEvents } from '@/lib/event'
import { notificationFilter } from '@/lib/notification' import { notificationFilter } from '@/lib/notification'
import { usePrimaryPage } from '@/PageManager' import { usePrimaryPage } from '@/PageManager'
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
import client from '@/services/client.service' import client from '@/services/client.service'
import storage from '@/services/local-storage.service' import storage from '@/services/local-storage.service'
import { kinds, NostrEvent } from 'nostr-tools' import { kinds, NostrEvent } from 'nostr-tools'
@ -33,7 +34,8 @@ export const useNotification = () => {
export function NotificationProvider({ children }: { children: React.ReactNode }) { export function NotificationProvider({ children }: { children: React.ReactNode }) {
const { current } = usePrimaryPage() const { current } = usePrimaryPage()
const active = useMemo(() => current === 'notifications', [current]) const active = useMemo(() => current === 'notifications', [current])
const { pubkey, notificationsSeenAt, updateNotificationsSeenAt } = useNostr() const { pubkey, relayList, notificationsSeenAt, updateNotificationsSeenAt } = useNostr()
const { favoriteRelays } = useFavoriteRelays()
const { hideUntrustedNotifications, isUserTrusted } = useUserTrust() const { hideUntrustedNotifications, isUserTrusted } = useUserTrust()
const { mutePubkeySet } = useMuteList() const { mutePubkeySet } = useMuteList()
const { hideContentMentioningMutedUsers } = useContentPolicy() const { hideContentMentioningMutedUsers } = useContentPolicy()
@ -106,8 +108,27 @@ export function NotificationProvider({ children }: { children: React.ReactNode }
try { try {
let eosed = false let eosed = false
const relayList = await client.fetchRelayList(pubkey) // Use proper fallback hierarchy: user's read/inbox relays → favorite relays → fast read relays
const notificationRelays = relayList.read.length > 0 ? relayList.read.slice(0, 5) : BIG_RELAY_URLS const userRelayList = relayList || { read: [], write: [] }
const userReadRelays = userRelayList.read || []
const userFavoriteRelays = favoriteRelays || []
// Build relay list with proper fallback hierarchy
let notificationRelays: string[] = []
if (userReadRelays.length > 0) {
// Priority 1: User's read/inbox relays (kind 10002)
notificationRelays = userReadRelays.slice(0, 5)
console.debug('[NotificationProvider] Using user read relays:', notificationRelays.length, 'relays')
} else if (userFavoriteRelays.length > 0) {
// Priority 2: User's favorite relays (kind 10012)
notificationRelays = userFavoriteRelays.slice(0, 5)
console.debug('[NotificationProvider] Using user favorite relays:', notificationRelays.length, 'relays')
} else {
// Priority 3: Fast read relays (reliable defaults)
notificationRelays = FAST_READ_RELAY_URLS.slice(0, 5)
console.debug('[NotificationProvider] Using fast read relays fallback:', notificationRelays.length, 'relays')
}
// Subscribe to discussion notifications (kind 11) // Subscribe to discussion notifications (kind 11)
// Subscribe to all discussions, not just subscribed topics // Subscribe to all discussions, not just subscribed topics

10
src/services/client.service.ts

@ -56,15 +56,15 @@ class ClientService extends EventTarget {
{ cacheMap: this.eventCacheMap } { cacheMap: this.eventCacheMap }
) )
private requestThrottle = new Map<string, number>() // Track request timestamps per relay private requestThrottle = new Map<string, number>() // Track request timestamps per relay
private readonly REQUEST_COOLDOWN = 3000 // 3 second cooldown between requests to prevent "too many REQs" private readonly REQUEST_COOLDOWN = 1000 // 1 second cooldown between requests (reduced from 3s)
private failureCount = new Map<string, number>() // Track consecutive failures per relay private failureCount = new Map<string, number>() // Track consecutive failures per relay
private readonly MAX_FAILURES = 1 // Max failures before exponential backoff (reduced to 1 for faster circuit breaker activation) private readonly MAX_FAILURES = 3 // Max failures before exponential backoff (increased from 1 for better reliability)
private circuitBreaker = new Map<string, number>() // Track when relays are temporarily disabled private circuitBreaker = new Map<string, number>() // Track when relays are temporarily disabled
private readonly CIRCUIT_BREAKER_TIMEOUT = 60000 // 60 second timeout for circuit breaker (increased for better stability) private readonly CIRCUIT_BREAKER_TIMEOUT = 30000 // 30 second timeout for circuit breaker (reduced from 60s)
private concurrentRequests = new Map<string, number>() // Track concurrent requests per relay private concurrentRequests = new Map<string, number>() // Track concurrent requests per relay
private readonly MAX_CONCURRENT_REQUESTS = 1 // Max concurrent requests per relay (reduced to prevent "too many REQs") private readonly MAX_CONCURRENT_REQUESTS = 2 // Max concurrent requests per relay (increased from 1)
private globalRequestThrottle = 0 // Global request throttle to prevent overwhelming all relays private globalRequestThrottle = 0 // Global request throttle to prevent overwhelming all relays
private readonly GLOBAL_REQUEST_COOLDOWN = 1000 // 1 second global cooldown between any relay requests private readonly GLOBAL_REQUEST_COOLDOWN = 500 // 0.5 second global cooldown (reduced from 1s)
private blacklistedRelays = new Map<string, number>() // Temporarily blacklist problematic relays private blacklistedRelays = new Map<string, number>() // Temporarily blacklist problematic relays
private readonly BLACKLIST_TIMEOUT = 300000 // 5 minutes blacklist timeout private readonly BLACKLIST_TIMEOUT = 300000 // 5 minutes blacklist timeout

Loading…
Cancel
Save