WebsockexNova (WebsockexNova v0.1.1)
View SourceWebsockexNova is a robust WebSocket client library for Elixir with a pluggable adapter architecture.
Architecture Overview
WebsockexNova employs a "thin adapter" architecture that separates concerns through:
- Behavioral Interfaces: Well-defined behaviors for various aspects of WebSocket handling
- Default Implementations: Ready-to-use default implementations of these behaviors
- Platform Adapters: Thin adapters that bridge to specific platforms/services
- Connection Management: Process-based connection handling with ownership semantics
This modular design allows for maximum flexibility while minimizing boilerplate code.
Key Components
- Connection: The core GenServer process managing the WebSocket lifecycle
- Client: A convenient API for interacting with connections
- Behaviors: Interfaces for connection, message, authentication, error handling, etc.
- Defaults: Ready-to-use implementations of all behaviors
- Platform Adapters: Thin adapters for specific WebSocket services
Basic Usage
# Start a connection to the Echo service
{:ok, conn} = WebsockexNova.Connection.start_link(
adapter: WebsockexNova.Platform.Echo.Adapter
)
# Send a message and get the response
{:text, response} = WebsockexNova.Client.send_text(conn, "Hello")
Using with Custom Handlers
# Start a connection with custom handlers
{:ok, conn} = WebsockexNova.Connection.start_link(
adapter: WebsockexNova.Platform.Echo.Adapter,
message_handler: MyApp.MessageHandler,
connection_handler: MyApp.ConnectionHandler
)
Creating a Client Module
defmodule MyApp.WebSocketClient do
use GenServer
def start_link(opts \\ []) do
GenServer.start_link(__MODULE__, opts)
end
def init(opts) do
# Start the WebSocket connection
{:ok, conn} = WebsockexNova.Connection.start_link(
adapter: WebsockexNova.Platform.Echo.Adapter
)
{:ok, %{conn: conn}}
end
# API functions
def send_message(client, message) do
GenServer.call(client, {:send, message})
end
# Callbacks
def handle_call({:send, message}, _from, %{conn: conn} = state) do
result = WebsockexNova.Client.send_text(conn, message)
{:reply, result, state}
end
end
Implementing Custom Handlers
Each aspect of WebSocket communication can be customized by implementing one of
the behaviors in WebsockexNova.Behaviors
:
defmodule MyApp.MessageHandler do
@behaviour WebsockexNova.Behaviors.MessageHandler
@impl true
def init(opts) do
{:ok, %{messages: []}}
end
@impl true
def handle_message(frame_type, data, state) do
IO.puts("Received #{frame_type} message: #{inspect(data)}")
new_state = update_in(state.messages, &[{frame_type, data} | &1])
{:ok, new_state}
end
end
Creating a Platform Adapter
To support a new WebSocket service, implement the WebsockexNova.Platform.Adapter
behavior:
defmodule MyApp.CustomAdapter do
use WebsockexNova.Platform.Adapter,
default_host: "api.example.com",
default_port: 443,
default_path: "/websocket"
@impl true
def handle_platform_message(message, state) do
# Custom message handling
{:reply, {:text, "Processed: #{inspect(message)}"}, state}
end
@impl true
def encode_auth_request(credentials) do
{:text, Jason.encode!(%{
type: "auth",
key: credentials.api_key,
secret: credentials.api_secret
})}
end
@impl true
def encode_subscription_request(channel, params) do
{:text, Jason.encode!(%{
type: "subscribe",
channel: channel,
params: params
})}
end
@impl true
def encode_unsubscription_request(channel) do
{:text, Jason.encode!(%{
type: "unsubscribe",
channel: channel
})}
end
end
Available Behaviors
ConnectionHandler
: Handle connection lifecycle eventsMessageHandler
: Process incoming WebSocket messagesSubscriptionHandler
: Manage channel subscriptionsAuthHandler
: Handle authenticationErrorHandler
: Process error scenariosRateLimitHandler
: Implement rate limitingLoggingHandler
: Provide logging functionalityMetricsCollector
: Collect metrics about WebSocket operations
Each behavior has a corresponding default implementation in the WebsockexNova.Defaults
namespace.