7.0 KiB
Migration Guide: ClientService Refactoring
Overview
The client.service.ts (4313 lines) has been refactored into focused service modules. This guide helps migrate existing code to use the new services.
New Service Architecture
1. QueryService (client-query.service.ts)
Purpose: Core query/subscription logic with race-based fetching
Key Methods:
query(urls, filter, onevent, options)- Core query with race strategiessubscribe(urls, filter, callbacks)- Relay subscriptionsfetchEvents(urls, filter, options)- Fetch events with cachingtrackEventSeenOn(eventId, relay)- Track where events were seengetSeenEventRelayUrls(eventId)- Get relays that saw an event
Migration: Most internal usage, but if you're calling query or subscribe directly, use queryService instead.
2. EventService (client-events.service.ts)
Purpose: Single event fetching and caching
Key Methods:
fetchEvent(id)- Fetch single event by IDfetchEventForceRetry(eventId)- Force retry fetchfetchEventWithExternalRelays(eventId, externalRelays)- Fetch with specific relaysaddEventToCache(event)- Add to session cachegetSessionEventsMatchingSearch(query, limit, allowedKinds)- Search session cacheclearCaches()- Clear all caches
Migration: Replace client.fetchEvent() with eventService.fetchEvent()
3. ReplaceableEventService (client-replaceable-events.service.ts)
Purpose: Replaceable events (profiles, relay lists, follow lists, etc.)
Key Methods:
fetchReplaceableEvent(pubkey, kind, d?)- Fetch replaceable eventfetchReplaceableEventsFromBigRelays(pubkeys, kind)- Batch fetchupdateReplaceableEventCache(event)- Update cacheclearCaches()- Clear caches
Migration: Replace client.fetchProfileEvent(), client.fetchRelayListEvent(), etc. with replaceableEventService.fetchReplaceableEvent()
4. MacroService (client-macro.service.ts)
Purpose: Macro-specific events (Bookstr, Wikistr, etc.)
Key Methods:
fetchMacroEvents(filters)- Fetch macro eventsgetCachedMacroEvents(filters)- Get from cache
Migration: Replace client.fetchBookstrEvents() with macroService.fetchMacroEvents()
5. CacheService (client-cache.service.ts)
Purpose: Universal cache-warming and refresh strategy
Key Methods:
warmupCache(config, fetchFn)- Warm up cache on loginscheduleRefresh(pubkey, kind, fetchFn)- Schedule background refreshgetProfileWithRefresh(pubkey, fetchFn)- Get profile with auto-refreshgetRelayListWithRefresh(pubkey, fetchFn)- Get relay list with auto-refreshisStale(pubkey, kind, cachedAt)- Check if cache is stalestartPeriodicRefresh(refreshFn)- Start periodic refresh
Migration: Use for cache-warming on login and background refresh
Files That Need Updates
High Priority (Direct client.service usage)
-
src/providers/NostrProvider/index.tsx- Uses:
client.fetchRelayList(),client.fetchProfileEvent(),client.fetchEvents() - Update: Use
replaceableEventService,eventService,queryService
- Uses:
-
src/hooks/useFetchProfile.tsx- Uses:
client.fetchProfile(),client.getProfileFromIndexedDB() - Update: Use
replaceableEventServiceor new profile service
- Uses:
-
src/hooks/useFetchEvent.tsx- Uses:
client.fetchEvent() - Update: Use
eventService.fetchEvent()
- Uses:
-
src/hooks/useFetchRelayList.tsx- Uses:
client.fetchRelayList() - Update: Use
replaceableEventServiceor new relay service
- Uses:
-
src/components/Profile/index.tsx- Uses:
client.fetchPaymentInfoEvent(),client.fetchEvents() - Update: Use
replaceableEventService,queryService
- Uses:
-
src/components/Profile/ProfileBookmarksAndHashtags.tsx- Uses:
client.fetchEvents(),client.fetchInterestListEvent() - Update: Use
queryService,replaceableEventService
- Uses:
Medium Priority (Indirect usage)
-
src/services/note-stats.service.ts- Uses:
client.fetchEvents() - Update: Use
queryService.fetchEvents()
- Uses:
-
src/services/mention-event-search.service.ts- Uses:
client.getSessionEventsMatchingSearch() - Update: Use
eventService.getSessionEventsMatchingSearch()
- Uses:
-
src/components/Bookstr/BookstrContent.tsx- Uses:
client.fetchBookstrEvents() - Update: Use
macroService.fetchMacroEvents()
- Uses:
-
src/components/Note/PublicationIndex/PublicationIndex.tsx- Uses:
client.fetchEvent(),indexedDb.getReplaceableEvent() - Update: Use
eventService.fetchEvent(),replaceableEventService
- Uses:
Low Priority (Internal services)
-
src/services/relay-selection.service.ts- Uses:
client.fetchRelayList() - Update: Use
replaceableEventServiceor new relay service
- Uses:
-
src/services/relay-info.service.ts- Uses:
client.fetchEvents() - Update: Use
queryService.fetchEvents()
- Uses:
Migration Pattern
Before:
import client from '@/services/client.service'
const profile = await client.fetchProfile(pubkey)
const event = await client.fetchEvent(eventId)
const relayList = await client.fetchRelayList(pubkey)
After:
import { eventService, replaceableEventService } from '@/services/client.service'
const profileEvent = await replaceableEventService.fetchReplaceableEvent(pubkey, kinds.Metadata)
const event = await eventService.fetchEvent(eventId)
const relayListEvent = await replaceableEventService.fetchReplaceableEvent(pubkey, kinds.RelayList)
Integration in Main ClientService
The main client.service.ts will be refactored to:
- Instantiate all sub-services
- Delegate method calls to appropriate services
- Maintain backward compatibility during transition
- Gradually remove old implementations
Cache Warming Integration
Add to NostrProvider initialization:
import cacheService from '@/services/client-cache.service'
// On login/initialization
await cacheService.warmupCache({
profilePubkeys: [account.pubkey, ...recentInteractions],
relayListPubkeys: [account.pubkey],
warmupFollowLists: true,
warmupMuteLists: true
}, {
fetchProfile: (id) => replaceableEventService.fetchReplaceableEvent(...),
fetchRelayList: (pubkey) => relayService.fetchRelayList(pubkey),
// ...
})
// Start periodic refresh
cacheService.startPeriodicRefresh(async (pubkey, kind) => {
await replaceableEventService.fetchReplaceableEvent(pubkey, kind)
})
Benefits
- Performance: Race-based fetching reduces wait times from 10-30s to 1-3s
- Cache efficiency: Universal cache-warming and refresh strategy
- Maintainability: Focused services are easier to understand and modify
- Testability: Services can be tested independently
- Extensibility: Easy to add new macro types or event types
Next Steps
- Complete remaining service extractions (ProfileService, RelayService, TimelineService)
- Update main
client.service.tsto orchestrate sub-services - Migrate high-priority files first
- Test thoroughly
- Remove old code once migration is complete