OddSockets Elixir SDK

Official Elixir SDK for OddSockets real-time messaging platform

Hex ready Elixir/OTP GenServer High Performance Fault Tolerant

Overview & Features

The OddSockets Elixir SDK provides a powerful, fault-tolerant interface for real-time messaging built on Elixir/OTP principles.

Elixir/OTP Native

Built with GenServers and supervision trees for maximum fault tolerance.

JavaScript Compatible

Full API compliance with JavaScript SDK pattern while maintaining Elixir idioms.

High Performance

Leverages Elixir's lightweight processes for concurrent message handling.

Fault Tolerant

Automatic reconnection and supervision for 99.9% uptime.

Cost Effective

No per-message pricing, industry-standard 32KB message limits.

Presence Tracking

Real-time user presence and state management with OTP patterns.

Installation

Add oddsockets to your list of dependencies in mix.exs:

elixir
def deps do
  [
    {:oddsockets, "~> 1.0.0"}
  ]
end

Then run:

bash
mix deps.get
elixir
def deps do
  [
    {:oddsockets, git: "https://github.com/oddsockets/elixir-sdk.git"}
  ]
end
elixir
def deps do
  [
    {:oddsockets, path: "../oddsockets"}
  ]
end

Quick Start

Basic Usage

elixir
# Start a client
{:ok, client} = OddSockets.start_link(api_key: "ak_live_1234567890abcdef")

# Get a channel
channel = OddSockets.channel(client, "my-channel")

# Subscribe to messages
:ok = OddSockets.Channel.subscribe(channel, fn message ->
  IO.inspect(message, label: "Received")
end)

# Publish a message
{:ok, result} = OddSockets.Channel.publish(channel, %{text: "Hello World!"})

GenServer Integration

elixir
defmodule MyApp.ChatServer do
  use GenServer

  def start_link(opts) do
    GenServer.start_link(__MODULE__, opts, name: __MODULE__)
  end

  def init(_opts) do
    {:ok, client} = OddSockets.start_link(api_key: "your-api-key")
    channel = OddSockets.channel(client, "chat-room")
    
    :ok = OddSockets.Channel.subscribe(channel, &handle_message/1)
    
    {:ok, %{client: client, channel: channel}}
  end

  defp handle_message(message) do
    IO.puts("Chat message: #{inspect(message)}")
  end
end

Event Handling

elixir
# Subscribe to client events
:ok = OddSockets.subscribe_events(client)

# Handle events in your process
receive do
  {:oddsockets_event, :connected} ->
    IO.puts("Connected to OddSockets!")
  
  {:oddsockets_event, {:error, reason}} ->
    IO.puts("Connection error: #{inspect(reason)}")
  
  {:oddsockets_event, {:worker_assigned, info}} ->
    IO.puts("Assigned to worker: #{info.worker_id}")
end

Configuration

Client Options

elixir
{:ok, client} = OddSockets.start_link(
  api_key: "your-api-key",           # Required: Your OddSockets API key
  user_id: "user-id",                # Optional: User identifier
  auto_connect: true,                # Optional: Auto-connect on creation
  options: %{
    timeout: 10_000                  # Optional: Connection timeout (ms)
  }
)

Channel Options

elixir
:ok = OddSockets.Channel.subscribe(channel, callback, %{
  max_history: 100,                  # Maximum history messages to retain
  retain_history: true,              # Whether to retain message history
  enable_presence: false             # Enable presence tracking
})

{:ok, result} = OddSockets.Channel.publish(channel, message, %{
  ttl: 3600,                         # Time to live (seconds)
  metadata: %{priority: "high"}      # Additional metadata
})

Application Configuration

elixir
# config/config.exs
config :oddsockets,
  api_key: "your-api-key",
  manager_url: "https://manager.oddsockets.com"

Examples

Explore comprehensive examples demonstrating the OddSockets Elixir SDK in action:

Performance & Compatibility

OddSockets Elixir SDK delivers superior performance with Elixir/OTP advantages:

<50ms
Latency
99.9%
Uptime
32KB
Max Message
1M+
Processes

Elixir Support

  • Elixir 1.12+ (OTP 24+)
  • Phoenix Framework
  • LiveView Integration
  • GenServer Patterns

OTP Features

  • Supervision Trees
  • Fault Tolerance
  • Hot Code Reloading
  • Distributed Systems

OTP Patterns & Integration

The OddSockets Elixir SDK is designed to work seamlessly with Elixir/OTP patterns and popular frameworks:

Phoenix Framework

elixir
defmodule MyAppWeb.ChatLive do
  use MyAppWeb, :live_view

  def mount(_params, _session, socket) do
    {:ok, client} = OddSockets.start_link(api_key: "your-api-key")
    channel = OddSockets.channel(client, "chat-room")
    
    :ok = OddSockets.Channel.subscribe(channel, fn message ->
      send(self(), {:new_message, message})
    end)

    {:ok, assign(socket, client: client, channel: channel, messages: [])}
  end

  def handle_info({:new_message, message}, socket) do
    messages = [message | socket.assigns.messages]
    {:noreply, assign(socket, messages: messages)}
  end

  def handle_event("send_message", %{"message" => text}, socket) do
    {:ok, _} = OddSockets.Channel.publish(socket.assigns.channel, %{
      text: text,
      user: "current_user"
    })
    
    {:noreply, socket}
  end
end

Supervision Tree

elixir
defmodule MyApp.Application do
  use Application

  def start(_type, _args) do
    children = [
      # Start OddSockets client as part of supervision tree
      {OddSockets, api_key: "your-api-key", name: MyApp.OddSocketsClient},
      
      # Other supervised processes
      MyApp.Repo,
      MyAppWeb.Endpoint,
      {MyApp.ChatManager, []}
    ]

    opts = [strategy: :one_for_one, name: MyApp.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

GenServer Pattern

elixir
defmodule MyApp.NotificationManager do
  use GenServer

  def start_link(opts) do
    GenServer.start_link(__MODULE__, opts, name: __MODULE__)
  end

  def init(_opts) do
    {:ok, client} = OddSockets.start_link(api_key: "your-api-key")
    
    # Subscribe to multiple channels
    channels = ["notifications", "alerts", "updates"]
    |> Enum.map(fn name ->
      channel = OddSockets.channel(client, name)
      :ok = OddSockets.Channel.subscribe(channel, &handle_notification/1)
      {name, channel}
    end)
    |> Map.new()

    {:ok, %{client: client, channels: channels}}
  end

  def broadcast_notification(type, message) do
    GenServer.cast(__MODULE__, {:broadcast, type, message})
  end

  def handle_cast({:broadcast, type, message}, state) do
    case Map.get(state.channels, type) do
      nil -> 
        {:noreply, state}
      channel ->
        {:ok, _} = OddSockets.Channel.publish(channel, message)
        {:noreply, state}
    end
  end

  defp handle_notification(message) do
    # Process incoming notifications
    IO.puts("Notification received: #{inspect(message)}")
  end
end

Task and Agent Integration

elixir
defmodule MyApp.MessageProcessor do
  def start_processing(api_key) do
    {:ok, client} = OddSockets.start_link(api_key: api_key)
    channel = OddSockets.channel(client, "processing-queue")
    
    # Use Agent to store state
    {:ok, agent} = Agent.start_link(fn -> %{processed: 0, errors: 0} end)
    
    # Subscribe with async processing
    :ok = OddSockets.Channel.subscribe(channel, fn message ->
      Task.start(fn ->
        process_message_async(message, agent)
      end)
    end)
    
    {:ok, {client, channel, agent}}
  end

  defp process_message_async(message, agent) do
    try do
      # Process the message
      result = process_message(message)
      
      # Update success counter
      Agent.update(agent, fn state ->
        %{state | processed: state.processed + 1}
      end)
      
      result
    rescue
      error ->
        # Update error counter
        Agent.update(agent, fn state ->
          %{state | errors: state.errors + 1}
        end)
        
        {:error, error}
    end
  end

  defp process_message(message) do
    # Your message processing logic here
    IO.puts("Processing: #{inspect(message)}")
    :ok
  end

  def get_stats(agent) do
    Agent.get(agent, & &1)
  end
end