%% Event handler management functions
handle_register_event_handler(State = #state{eventHandlers = Handlers}, HandlerPid, IntervalMs) ->
case maps:is_key(HandlerPid, Handlers) of
true ->
%% Already registered, update interval
io:format("[Peer] Updating event handler ~p interval to ~pms~n", [HandlerPid, IntervalMs]),
OldHandler = maps:get(HandlerPid, Handlers),
%% Cancel old timer
case maps:get(timer_ref, OldHandler, undefined) of
undefined -> ok;
OldTimerRef -> erlang:cancel_timer(OldTimerRef)
end,
%% Start new timer
TimerRef = erlang:send_after(IntervalMs, self(), {notificationTimer, HandlerPid}),
NewHandler = OldHandler#{interval => IntervalMs, timer_ref => TimerRef},
State#state{eventHandlers = maps:put(HandlerPid, NewHandler, Handlers)};
false ->
%% New registration
io:format("[Peer] Registered event handler ~p with interval ~pms~n", [HandlerPid, IntervalMs]),
TimerRef = erlang:send_after(IntervalMs, self(), {notificationTimer, HandlerPid}),
Handler = #{
interval => IntervalMs,
timer_ref => TimerRef,
pending => sets:new()
},
State#state{eventHandlers = maps:put(HandlerPid, Handler, Handlers)}
end.
handle_unregister_event_handler(State = #state{eventHandlers = Handlers}, HandlerPid) ->
case maps:take(HandlerPid, Handlers) of
error ->
io:format("[Peer] Event handler ~p not found~n", [HandlerPid]),
State;
{Handler, NewHandlers} ->
io:format("[Peer] Unregistered event handler ~p~n", [HandlerPid]),
%% Cancel timer
case maps:get(timer_ref, Handler, undefined) of
undefined -> ok;
TimerRef -> erlang:cancel_timer(TimerRef)
end,
State#state{eventHandlers = NewHandlers}
end.
handle_notification_timer(State = #state{eventHandlers = Handlers}, HandlerPid) ->
case maps:get(HandlerPid, Handlers, undefined) of
undefined ->
%% Handler was unregistered, ignore
State;
Handler ->
Pending = maps:get(pending, Handler),
Interval = maps:get(interval, Handler),
%% Send notifications for all pending channels
case sets:size(Pending) of
0 ->
ok; % Nothing to notify
_ ->
PendingList = sets:to_list(Pending),
lists:foreach(fun(Chan) ->
try
HandlerPid ! {channel_event, {new_messages, Chan}}
catch
_:_ ->
io:format("[Peer] Failed to send event to handler ~p~n", [HandlerPid])
end
end, PendingList),
io:format("[Peer] Notified handler ~p of ~p channels~n", [HandlerPid, length(PendingList)])
end,
%% Clear pending and restart timer
TimerRef = erlang:send_after(Interval, self(), {notificationTimer, HandlerPid}),
NewHandler = Handler#{pending => sets:new(), timer_ref => TimerRef},
State#state{eventHandlers = maps:put(HandlerPid, NewHandler, Handlers)}
end.
mark_channels_for_notification(State = #state{eventHandlers = Handlers}, Channels) ->
case maps:size(Handlers) of
0 ->
State; % No handlers, nothing to do
_ ->
%% Add channels to pending set for all handlers
NewHandlers = maps:map(fun(_Pid, Handler) ->
Pending = maps:get(pending, Handler),
NewPending = lists:foldl(fun sets:add_element/2, Pending, Channels),
Handler#{pending => NewPending}
end, Handlers),
State#state{eventHandlers = NewHandlers}
end.