WebsockexNova.Message.SubscriptionManager (WebsockexNova v0.1.0)

View Source

Manages WebSocket subscriptions with support for persistence and automatic resubscription.

The SubscriptionManager provides a higher-level interface for working with subscriptions, delegating the actual subscription tracking to a SubscriptionHandler behavior implementation. It adds features like:

  • Centralized subscription management
  • Automatic resubscription after reconnection
  • Subscription state persistence
  • Helper functions for monitoring subscriptions

Usage Example

alias WebsockexNova.Message.SubscriptionManager
alias MyApp.Crypto.DeribitSubscriptionHandler

# Initialize a subscription manager
{:ok, manager} = SubscriptionManager.new(DeribitSubscriptionHandler)

# Subscribe to channels
{:ok, sub_id1, manager} = SubscriptionManager.subscribe(manager, "market.btcusd.trades", %{frequency: "100ms"})
{:ok, sub_id2, manager} = SubscriptionManager.subscribe(manager, "market.btcusd.orderbook", %{depth: 10})

# Handle subscription responses
response = %{"type" => "subscribed", "id" => sub_id1}
{:ok, manager} = SubscriptionManager.handle_response(manager, response)

# When connection is lost, prepare for reconnection
{:ok, manager} = SubscriptionManager.prepare_for_reconnect(manager)

# After reconnection, resubscribe to channels
results = SubscriptionManager.resubscribe_after_reconnect(manager)
# Process results and get the updated manager
[{:ok, new_sub_id1, manager} | _] = results

# Check active subscriptions
active = SubscriptionManager.active_subscriptions(manager)

State Persistence

To persist subscriptions across process restarts:

# Export state before process terminates
state_to_save = SubscriptionManager.export_state(manager)

# Later, when restarting:
{:ok, manager} = SubscriptionManager.new(DeribitSubscriptionHandler)
{:ok, restored_manager} = SubscriptionManager.import_state(manager, state_to_save)

Summary

Functions

Retrieves the active (confirmed) subscriptions.

Exports the subscription state for persistence.

Finds a subscription ID by channel name.

Processes a subscription-related response message.

Imports previously exported subscription state.

Creates a new subscription manager with the specified handler module.

Prepares for reconnection by storing active subscriptions in state.

Resubscribes to all stored subscriptions after a successful reconnect.

Subscribes to a channel using the configured handler.

Unsubscribes from a channel using the configured handler.

Types

t()

@type t() :: %WebsockexNova.Message.SubscriptionManager{
  handler: module(),
  state: map()
}

Functions

active_subscriptions(manager)

@spec active_subscriptions(t()) :: %{
  required(WebsockexNova.Behaviors.SubscriptionHandler.subscription_id()) =>
    term()
}

Retrieves the active (confirmed) subscriptions.

Parameters

  • manager - The subscription manager

Returns

  • A map of subscription IDs to subscription details

export_state(manager)

@spec export_state(t()) :: map()

Exports the subscription state for persistence.

This is useful for saving the state before a process terminates, so it can be restored later.

Parameters

  • manager - The subscription manager

Returns

  • A map containing the serializable state

find_subscription_by_channel(manager, channel)

Finds a subscription ID by channel name.

Parameters

  • manager - The subscription manager
  • channel - The channel name to look up

Returns

  • The subscription ID if found, nil otherwise

handle_response(manager, response)

@spec handle_response(
  t(),
  WebsockexNova.Behaviors.SubscriptionHandler.subscription_response()
) ::
  {:ok, t()} | {:error, term(), t()}

Processes a subscription-related response message.

Parameters

  • manager - The subscription manager
  • response - The response message from the server

Returns

  • {:ok, updated_manager} - Response processed successfully
  • {:error, reason, updated_manager} - Error in response

import_state(manager, exported_state)

@spec import_state(t(), map()) :: {:ok, t()}

Imports previously exported subscription state.

This is useful for restoring state after process restart.

Parameters

  • manager - The subscription manager
  • exported_state - The state previously exported with export_state/1

Returns

  • {:ok, updated_manager} - Successfully imported state

new(handler_module, initial_state \\ %{})

@spec new(module(), map()) :: {:ok, t()}

Creates a new subscription manager with the specified handler module.

Parameters

  • handler_module - Module that implements the SubscriptionHandler behavior
  • initial_state - Optional initial state for the handler (default: %{})

Returns

  • {:ok, manager} - A new subscription manager

prepare_for_reconnect(manager)

@spec prepare_for_reconnect(t()) :: {:ok, t()}

Prepares for reconnection by storing active subscriptions in state.

This should be called before a reconnection attempt to ensure subscriptions can be restored after reconnection.

Parameters

  • manager - The subscription manager

Returns

  • {:ok, updated_manager} - Successfully prepared for reconnect

resubscribe_after_reconnect(manager)

@spec resubscribe_after_reconnect(t()) :: [
  {:ok, WebsockexNova.Behaviors.SubscriptionHandler.subscription_id(), t()}
  | {:error, term(), t()}
]

Resubscribes to all stored subscriptions after a successful reconnect.

This should be called after a successful reconnection to restore previously active subscriptions.

Parameters

  • manager - The subscription manager with stored subscriptions

Returns

  • A list of subscription results, each being {:ok, subscription_id, updated_manager} or {:error, reason, updated_manager}

subscribe(manager, channel, params)

Subscribes to a channel using the configured handler.

Parameters

  • manager - The subscription manager
  • channel - The channel to subscribe to
  • params - Optional parameters for the subscription

Returns

  • {:ok, subscription_id, updated_manager} - Successful subscription with ID
  • {:error, reason, updated_manager} - Failed to subscribe

unsubscribe(manager, subscription_id)

@spec unsubscribe(t(), WebsockexNova.Behaviors.SubscriptionHandler.subscription_id()) ::
  {:ok, t()} | {:error, term(), t()}

Unsubscribes from a channel using the configured handler.

Parameters

  • manager - The subscription manager
  • subscription_id - The ID of the subscription to remove

Returns

  • {:ok, updated_manager} - Successfully unsubscribed
  • {:error, reason, updated_manager} - Failed to unsubscribe