Skip to content

ApplesauceRelayPool

The ApplesauceRelayPool is an advanced implementation of the RelayHandler interface that uses the applesauce-relay library. It provides sophisticated relay management with automatic reconnection, connection monitoring, and robust subscription handling.

The ApplesauceRelayPool offers enhanced features compared to the basic SimpleRelayPool:

  • Automatic Connection Management: Uses RelayPool for efficient connection handling
  • Connection Monitoring: Monitors relay connections and automatically resubscribes when connections are lost
  • Retry Logic: Built-in retry mechanisms for failed operations
  • Observable-based Architecture: Leverages RxJS-style observables for event handling
  • Advanced Subscription Management: Persistent subscriptions with automatic reconnection

This implementation is ideal for applications that require more sophisticated relay management and better resilience against network interruptions.

The constructor takes a single argument:

  • relayUrls: An array of strings, where each string is the URL of a Nostr relay (e.g., wss://relay.damus.io).
import { ApplesauceRelayPool } from "@contextvm/sdk";
import { NostrClientTransport } from "@contextvm/sdk";
// 1. Define the list of relays you want to connect to
const myRelays = [
"wss://relay.damus.io",
"wss://relay.primal.net",
"wss://nos.lol",
];
// 2. Create an instance of the ApplesauceRelayPool
const relayPool = new ApplesauceRelayPool(myRelays);
// 3. Pass the instance to a transport
const transport = new NostrClientTransport({
relayHandler: relayPool,
// ... other options
});

The ApplesauceRelayPool implements the RelayHandler interface using the applesauce-relay library:

  • connect(): Validates relay URLs and initializes the RelayPool. The pool automatically manages connections to relays as needed.
  • disconnect(): Closes all active subscriptions and clears internal state. Note that the underlying RelayPool manages connections automatically.
  • publish(event): Uses relayGroup.publish() which includes automatic retry logic. The method returns a Promise that resolves when the publish operation completes.
  • subscribe(filters, onEvent, onEose): Creates a persistent subscription using relayGroup.subscription() with automatic reconnection. Subscriptions are tracked internally for lifecycle management.
  • unsubscribe(): Closes all active subscriptions and clears the internal subscription tracking.

The pool automatically monitors relay connections and triggers resubscription when connections are lost:

private setupConnectionMonitoring(): void {
this.pool.relays$.subscribe((relays) => {
relays.forEach((relay) => {
relay.connected$.subscribe((connected) => {
if (!connected) {
this.resubscribeAll();
}
});
});
});
}

When a relay connection is lost and reestablished, the pool automatically resubscribes to all active subscriptions:

private resubscribeAll(): void {
this.subscriptions.forEach((sub) => {
if (sub.closer) sub.closer.unsubscribe();
sub.closer = this.createSubscription(
sub.filters,
sub.onEvent,
sub.onEose,
);
});
}

The implementation includes comprehensive error handling for both publishing and subscription operations:

  • Publish Errors: Logs warnings for failed publishes but doesn’t reject the Promise unless there’s a critical error
  • Subscription Errors: Removes failed subscriptions from tracking and logs the error
FeatureSimpleRelayPoolApplesauceRelayPool
Librarynostr-toolsapplesauce-relay
Connection ManagementManual connection trackingAutomatic connection management
ReconnectionManual reconnection logicAutomatic reconnection with monitoring
Retry LogicBasic retry with exponential backoffBuilt-in retry mechanisms
Subscription PersistenceManual resubscriptionAutomatic resubscription on reconnect
Error HandlingBasic error loggingComprehensive error handling with cleanup

Consider using ApplesauceRelayPool when:

  • You need robust connection management and automatic reconnection
  • Your application requires high availability and resilience
  • You want advanced subscription management with automatic recovery
  • You’re building a production application that needs to handle network interruptions gracefully

For simpler use cases or when you want to minimize dependencies, the SimpleRelayPool may be sufficient.