AshDispatch.Helpers.CounterLoader (AshDispatch v0.5.1)

View Source

Helper for loading initial counter values when users connect.

This module automatically discovers counter definitions from your Ash resources and loads their current values. No manual configuration required!

How It Works

  1. Discovers all resources using AshDispatch.Resource extension
  2. Reads counter definitions from the counters DSL section
  3. Executes queries based on DSL configuration
  4. Returns a map of counter names to their current values

Usage in Phoenix Channels

defmodule MyAppWeb.UserChannel do
  use Phoenix.Channel

  alias AshDispatch.Helpers.CounterLoader

  def join("user:" <> user_id, _params, socket) do
    # Load initial counter values for this user
    counters = CounterLoader.load_counters_for_user(
      user_id,
      is_admin: user_is_admin?(user_id)
    )

    {:ok, %{counters: counters}, assign(socket, :user_id, user_id)}
  end

  # Listen for counter broadcasts
  def handle_info({:counter_update, counter_name, count, metadata}, socket) do
    push(socket, "counter_update", %{
      counter: counter_name,
      count: count,
      invalidate_queries: metadata.invalidate_queries
    })

    {:noreply, socket}
  end
end

Frontend Integration

// React/TypeScript example
channel.on("counter_update", (payload) => {
  // Update counter in state
  setCounters(prev => ({
    ...prev,
    [payload.counter]: payload.count
  }));

  // Invalidate related queries
  payload.invalidate_queries.forEach(queryKey => {
    queryClient.invalidateQueries([queryKey]);
  });
});

Counter Definition

Counters are defined in resource DSL:

defmodule MyApp.Orders.ProductOrder do
  use Ash.Resource,
    extensions: [AshDispatch.Resource]

  counters do
    counter :pending_orders do
      trigger_on [:create, :complete]
      counter_name :pending_orders
      query_filter [status: :pending]
      audience :user
      invalidates ["orders"]
    end
  end
end

The CounterLoader automatically discovers and uses these definitions!

Summary

Functions

Load all counter values for a specific user.

Functions

load_counters_for_user(user_id, opts \\ [])

Load all counter values for a specific user.

Automatically discovers counter definitions from resources and executes queries based on user's audiences (derived from configured recipient filters).

Returns a map of counter names to their current values.

Options

  • :domains - List of Ash domains to search for resources (defaults to all configured domains)

Examples

# Load counters for any user (automatically determines audiences)
CounterLoader.load_counters_for_user("user-123")
#=> %{pending_orders: 5, cart_items: 3}

# Admin user automatically gets admin counters
CounterLoader.load_counters_for_user("admin-456")
#=> %{pending_orders: 12, admin_pending_reseller_requests: 3}

# Load from specific domains only
CounterLoader.load_counters_for_user("user-123", domains: [MyApp.Orders])
#=> %{pending_orders: 5}