refactor(lists): route follows + hashtag-prefs subs through SubscriptionManager (P4)

The two feed-driving list subscriptions (kind-30000 follows, kind-30015/30005
hashtag prefs) now go through the L1 SubscriptionManager instead of the global
relaySubscriptionService singleton: centralized dedup + reconnect re-issue (the
lists self-heal after a relay drop). Handles are stored and closed on teardown;
relaySubscriptionService is retained as the manager-less fallback.

Verified: subscriptions-manager/-feed + hashtag-preferences suites pass (32);
flaky multi-relay harness still all-PASS; pool-access lint clean.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
thePR0M3TH3ANandClaude Opus 4.8 committed 2026-06-14 16:08:54 -04:00
1 parent 5c494b8961
commit 09d0e045e8
2 files changed
+51

No files matched your search

+25
View File
@@ -325,6 +325,14 @@ class HashtagPreferencesService {
}
stopHashtagPreferencesSubscription() {
if (this.subscriptionHandle) {
try {
this.subscriptionHandle.close();
} catch (error) {
devLogger.warn(`${LOG_PREFIX} Failed to close hashtag subscription handle`, error);
}
this.subscriptionHandle = null;
}
if (this.subscriptionKey) {
relaySubscriptionService.stopSubscription(this.subscriptionKey, "reset");
this.subscriptionKey = null;
@@ -353,6 +361,23 @@ class HashtagPreferencesService {
const key = `hashtags:${normalized}`;
this.subscriptionKey = key;
// Route through the L1 SubscriptionManager when available (dedup + reconnect
// re-issue); fall back to relaySubscriptionService in manager-less envs.
const manager =
typeof nostrClient.getSubscriptionManager === "function"
? nostrClient.getSubscriptionManager()
: null;
if (manager) {
this.subscriptionHandle = manager.subscribe({
key,
relays,
filters,
label: "hashtag-preferences",
onEvent: (event) => this.handleHashtagPreferencesEvent(event),
});
return this.subscriptionHandle;
}
return relaySubscriptionService.ensureSubscription({
key,
pool: nostrClient.pool,
+26
View File
@@ -851,6 +851,14 @@ class SubscriptionsManager {
}
stopSubscriptionListSubscription() {
if (this.subscriptionHandle) {
try {
this.subscriptionHandle.close();
} catch (error) {
devLogger.warn("[SubscriptionsManager] Failed to close subscription handle", error);
}
this.subscriptionHandle = null;
}
if (this.subscriptionKey) {
relaySubscriptionService.stopSubscription(this.subscriptionKey, "reset");
this.subscriptionKey = null;
@@ -874,6 +882,24 @@ class SubscriptionsManager {
},
];
// Route through the L1 SubscriptionManager when available: centralized
// dedup + reconnect re-issue (so the follows list self-heals after a relay
// drop). Falls back to relaySubscriptionService in manager-less envs.
const manager =
typeof nostrClient.getSubscriptionManager === "function"
? nostrClient.getSubscriptionManager()
: null;
if (manager) {
this.subscriptionHandle = manager.subscribe({
key,
relays,
filters,
label: "subscription-list",
onEvent: (event) => this.handleSubscriptionListEvent(event),
});
return this.subscriptionHandle;
}
return relaySubscriptionService.ensureSubscription({
key,
pool: nostrClient.pool,