Status Notifications Specification

View Source

Overview

Brama provides a comprehensive event notification system that allows applications to react to connection status changes. This document outlines how the notification system works, the types of events generated, and how to subscribe to and handle these events.

Event Types

Brama generates the following types of events:

Event TypeDescription
:state_changeConnection state has changed (e.g., closed to open)
:registrationNew connection registered with the system
:failureConnection failure reported
:successConnection success reported
:expiryCircuit expiry time reached
:cleanupConnection removed during cleanup
:circuit_openedCircuit has been opened
:circuit_closedCircuit has been closed
:circuit_resetCircuit has been reset
:connection_registeredNew connection registered
:connection_unregisteredConnection unregistered
:circuit_half_openedCircuit has transitioned to half-open
:connection_removedConnection has been removed

Event Data Structure

Each event contains detailed information about the connection and the event itself:

%{
  event: :state_change,          # Type of event
  timestamp: 1630000000000,      # When the event occurred
  connection: "payment_api",     # Connection identifier
  scope: "payments",             # Connection scope
  data: %{                       # Event-specific data
    previous_state: :closed,
    new_state: :open,
    reason: "Threshold exceeded",
    failure_count: 10
  }
}

Subscription API

Global Subscription

Subscribe to all events for all connections:

Brama.subscribe()

Filtered Subscription

Subscribe to specific events or connections:

# Subscribe to specific event types
Brama.subscribe(events: [:state_change, :failure])

# Subscribe to specific connection
Brama.subscribe(connection: "payment_api")

# Subscribe to scope
Brama.subscribe(scope: "payments")

# Combine filters
Brama.subscribe(
  events: [:state_change],
  connection: "payment_api"
)

Unsubscribing

Unsubscribe using similar patterns:

Brama.unsubscribe()  # Unsubscribe from all
Brama.unsubscribe(connection: "payment_api")  # Specific unsubscribe

Event Handling

Events are delivered as standard Elixir messages to the subscribing process:

def handle_info({:brama_event, event}, state) do
  # Handle the event
  Logger.info("Connection #{event.connection} changed to #{event.data.new_state}")
  {:noreply, state}
end

Implementation Details

Event Manager

  • Implemented using Elixir's Registry or GenStage (depending on volume needs)
  • Maintains a list of subscribers and their filter preferences
  • Efficiently distributes events only to interested subscribers

Performance Considerations

  • Event generation is asynchronous to prevent blocking
  • Subscription filters are applied at the source to minimize message volume
  • High-volume systems can use batched event delivery

Notification Behavior

Events have the following delivery guarantees:

  • At-least-once delivery for critical state changes
  • No guaranteed order of events
  • No persistence of events (transient in-memory only)

Integration with Monitoring Systems

For integration with external monitoring systems, Brama provides:

# Custom event handler for integration
Brama.subscribe(handler: MyApp.MonitoringHandler)

# Telemetry integration
:telemetry.execute(
  [:brama, :connection, :state_change],
  %{duration: System.monotonic_time() - start_time},
  %{connection: "payment_api", previous_state: :closed, new_state: :open}
)

Example Usage

defmodule MyApp.ConnectionMonitor do
  use GenServer

  def start_link(_) do
    GenServer.start_link(__MODULE__, %{})
  end

  def init(state) do
    # Subscribe to all state changes
    Brama.subscribe(events: [:state_change])
    {:ok, state}
  end

  def handle_info({:brama_event, event}, state) do
    if event.data.new_state == :open do
      # Alert on circuit open
      MyApp.Alerts.send("Circuit opened for #{event.connection}")
    end
    
    {:noreply, state}
  end
end