AshDispatch.Helpers.CounterLoader (AshDispatch v0.5.0)
View SourceHelper 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
- Discovers all resources using
AshDispatch.Resourceextension - Reads counter definitions from the
countersDSL section - Executes queries based on DSL configuration
- 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
endFrontend 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
endThe CounterLoader automatically discovers and uses these definitions!
Summary
Functions
Load all counter values for a specific user.
Functions
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}