WebsockexNova.Adapter (WebsockexNova v0.1.1)
View SourceMacro for building WebsockexNova adapters with minimal boilerplate.
This macro provides a convenient way to create platform-specific WebSocket adapters by automatically implementing all required behaviors with sensible defaults. You only need to override the specific behaviors needed for your use case.
Basic Usage
defmodule MyApp.MyAdapter do
use WebsockexNova.Adapter
# Override only what you need:
@impl WebsockexNova.Behaviors.MessageHandler
def handle_message(message, state) do
# Custom message handling
{:ok, decoded_message, state}
end
end
What this macro does
- Declares all core
@behaviour
attributes (AuthHandler, ConnectionHandler, etc.) - Injects default implementations for all callbacks, delegating to
WebsockexNova.Defaults.*
- Allows you to override any callback by implementing it in your module
- Imports necessary aliases for convenient access to behaviors and defaults
Examples
Simple adapter with custom connection info
defmodule MyApp.EchoAdapter do
use WebsockexNova.Adapter
@impl WebsockexNova.Behaviors.ConnectionHandler
def connection_info(opts) do
{:ok, Map.merge(%{
host: "echo.websocket.org",
port: 443,
path: "/",
transport: :tls
}, opts)}
end
end
Financial trading adapter with authentication
defmodule MyApp.TradingAdapter do
use WebsockexNova.Adapter
@impl WebsockexNova.Behaviors.ConnectionHandler
def connection_info(opts) do
{:ok, Map.merge(%{
host: "api.exchange.com",
port: 443,
path: "/ws/v2",
transport: :tls
}, opts)}
end
@impl WebsockexNova.Behaviors.AuthHandler
def authenticate(conn, auth_config, state) do
# Send authentication message
auth_msg = %{
method: "auth",
params: %{
api_key: auth_config.api_key,
api_secret: auth_config.api_secret
}
}
WebsockexNova.Client.send_message(conn, auth_msg)
{:ok, state}
end
@impl WebsockexNova.Behaviors.MessageHandler
def handle_message(%{"method" => "auth", "result" => true}, state) do
# Authentication successful
{:ok, %{authenticated: true}, Map.put(state, :authenticated, true)}
end
def handle_message(message, state) do
# Decode JSON messages
with {:ok, decoded} <- Jason.decode(message) do
{:ok, decoded, state}
else
_ -> {:error, :invalid_json, state}
end
end
end
Gaming adapter with custom subscription handling
defmodule MyApp.GameAdapter do
use WebsockexNova.Adapter
alias WebsockexNova.Message.SubscriptionManager
@impl WebsockexNova.Behaviors.SubscriptionHandler
def handle_subscription(channel, opts, conn, state) do
# Custom subscription format for game events
subscribe_msg = %{
action: "subscribe",
channel: channel,
params: opts || %{}
}
case WebsockexNova.Client.send_message(conn, subscribe_msg) do
{:ok, _} ->
manager = Map.get(state, :subscription_manager, SubscriptionManager.new())
updated_manager = SubscriptionManager.add_subscription(manager, channel, opts)
{:ok, %{}, Map.put(state, :subscription_manager, updated_manager)}
error ->
error
end
end
@impl WebsockexNova.Behaviors.MessageHandler
def handle_message(%{"type" => "game_event"} = message, state) do
# Handle game-specific events
{:ok, message, state}
end
def handle_message(message, state) do
DefaultMessageHandler.handle_message(message, state)
end
end
Available Behaviors
The macro automatically implements these behaviors with default implementations:
WebsockexNova.Behaviors.AuthHandler
- Authentication flowWebsockexNova.Behaviors.ConnectionHandler
- Connection lifecycleWebsockexNova.Behaviors.ErrorHandler
- Error handling strategiesWebsockexNova.Behaviors.MessageHandler
- Message processingWebsockexNova.Behaviors.SubscriptionHandler
- Channel subscriptions
Note: LoggingHandler, MetricsCollector, and RateLimitHandler are not included by default since they're typically configured at the client level rather than the adapter level.
Tips
- Only override the behaviors you need to customize
- Call the default implementations when you want to extend rather than replace behavior
- Use pattern matching in message handlers for efficient message routing
- Store adapter-specific state in the adapter_state field of the connection
See the WebsockexNova.Examples.AdapterDeribit
module for a complete real-world example.