Current section

Files

Jump to
reckon_db src reckon_db_tracker_group.erl
Raw

src/reckon_db_tracker_group.erl

%% @doc Tracker group management for reckon-db
%%
%% Uses pg (process groups) for managing tracker processes.
%% Trackers receive notifications about subscription lifecycle events.
%%
%% This module provides:
%% - Process group management for tracker processes
%% - Notification broadcasting for created/deleted/updated events
%%
%% Features that can be tracked:
%% - subscriptions: Subscription lifecycle
%% - streams: Stream lifecycle
%% - snapshots: Snapshot lifecycle
%%
%% @author rgfaber
-module(reckon_db_tracker_group).
-include("reckon_db.hrl").
-export([
join/3,
leave/3,
members/2,
group_key/2,
notify_created/3,
notify_deleted/3,
notify_updated/3
]).
%%====================================================================
%% Types
%%====================================================================
-type store_id() :: atom().
-type feature() :: subscriptions | streams | snapshots | atom().
%%====================================================================
%% API
%%====================================================================
%% @doc Generate the group key for a feature's trackers
-spec group_key(store_id(), feature()) -> integer().
group_key(StoreId, Feature) ->
erlang:phash2({StoreId, Feature, trackers}).
%% @doc Join one or more processes to the tracker group for a feature
-spec join(store_id(), feature(), pid() | [pid()]) -> ok.
join(StoreId, Feature, PidOrPids) ->
Group = group_key(StoreId, Feature),
ok = pg:join(?RECKON_DB_PG_SCOPE, Group, PidOrPids),
ok.
%% @doc Remove one or more processes from the tracker group
-spec leave(store_id(), feature(), pid() | [pid()]) -> ok.
leave(StoreId, Feature, PidOrPids) ->
Group = group_key(StoreId, Feature),
ok = pg:leave(?RECKON_DB_PG_SCOPE, Group, PidOrPids),
ok.
%% @doc Get all member processes tracking a feature
-spec members(store_id(), feature()) -> [pid()].
members(StoreId, Feature) ->
Group = group_key(StoreId, Feature),
pg:get_members(?RECKON_DB_PG_SCOPE, Group).
%% @doc Notify all trackers that a feature instance was created
-spec notify_created(store_id(), feature(), term()) -> ok.
notify_created(StoreId, Feature, Data) ->
Msg = created(Feature, Data),
Pids = members(StoreId, Feature),
lists:foreach(fun(Pid) -> Pid ! Msg end, Pids),
ok.
%% @doc Notify all trackers that a feature instance was deleted
-spec notify_deleted(store_id(), feature(), term()) -> ok.
notify_deleted(StoreId, Feature, Data) ->
Msg = deleted(Feature, Data),
Pids = members(StoreId, Feature),
lists:foreach(fun(Pid) -> Pid ! Msg end, Pids),
ok.
%% @doc Notify all trackers that a feature instance was updated
-spec notify_updated(store_id(), feature(), term()) -> ok.
notify_updated(StoreId, Feature, Data) ->
Msg = updated(Feature, Data),
Pids = members(StoreId, Feature),
lists:foreach(fun(Pid) -> Pid ! Msg end, Pids),
ok.
%%====================================================================
%% Internal functions
%%====================================================================
%% @private Create a feature_created message
-spec created(feature(), term()) -> {feature_created, feature(), term()}.
created(Feature, Data) ->
{feature_created, Feature, Data}.
%% @private Create a feature_deleted message
-spec deleted(feature(), term()) -> {feature_deleted, feature(), term()}.
deleted(Feature, Data) ->
{feature_deleted, Feature, Data}.
%% @private Create a feature_updated message
-spec updated(feature(), term()) -> {feature_updated, feature(), term()}.
updated(Feature, Data) ->
{feature_updated, Feature, Data}.