Files
EventHubBack/src/core/core_calendar_follow.erl
T
aleksey 59220b955e
CI / test (push) Failing after 6m39s
CI / deploy-ift (push) Has been skipped
CI / e2e-ift (push) Has been skipped
CI / deploy-stage (push) Has been skipped
CI / e2e-stage (push) Has been skipped
feat: calendar follow API (POST/DELETE follow, GET following). Refs EventHub/EventHubFront#9
2026-07-20 22:10:48 +03:00

112 lines
4.1 KiB
Erlang
Executable File

%%%-------------------------------------------------------------------
%%% @doc Хранение follow чужих календарей (уникальность calendar_id+user_id).
%%% @end
%%%-------------------------------------------------------------------
-module(core_calendar_follow).
-include("records.hrl").
-export([follow/2, unfollow/2, is_following/2, list_by_user/1,
list_by_calendar/1, delete_by_calendar/1]).
%%%-------------------------------------------------------------------
%%% @doc Подписаться на календарь. Идемпотентно, если уже follow.
%%% @end
%%%-------------------------------------------------------------------
-spec follow(CalendarId :: binary(), UserId :: binary()) ->
{ok, #calendar_follow{}} | {error, term()}.
follow(CalendarId, UserId) ->
Now = calendar:universal_time(),
F = fun() ->
case find(CalendarId, UserId) of
[#calendar_follow{} = Existing] ->
{ok, Existing};
[] ->
Rec = #calendar_follow{
id = infra_utils:generate_id(16),
calendar_id = CalendarId,
user_id = UserId,
created_at = Now
},
mnesia:write(Rec),
{ok, Rec}
end
end,
case mnesia:transaction(F) of
{atomic, Result} -> Result;
{aborted, Reason} -> {error, Reason}
end.
%%%-------------------------------------------------------------------
%%% @doc Отписаться. Идемпотентно, если follow нет.
%%% @end
%%%-------------------------------------------------------------------
-spec unfollow(CalendarId :: binary(), UserId :: binary()) -> ok | {error, term()}.
unfollow(CalendarId, UserId) ->
F = fun() ->
case find(CalendarId, UserId) of
[] ->
ok;
[#calendar_follow{id = Id}] ->
mnesia:delete({calendar_follow, Id}),
ok
end
end,
case mnesia:transaction(F) of
{atomic, ok} -> ok;
{aborted, Reason} -> {error, Reason}
end.
%%%-------------------------------------------------------------------
%%% @doc Есть ли follow у пользователя.
%%% @end
%%%-------------------------------------------------------------------
-spec is_following(UserId :: binary(), CalendarId :: binary()) -> boolean().
is_following(UserId, CalendarId) ->
case mnesia:dirty_match_object(
#calendar_follow{calendar_id = CalendarId, user_id = UserId, _ = '_'}) of
[] -> false;
_ -> true
end.
%%%-------------------------------------------------------------------
%%% @doc Все follow пользователя.
%%% @end
%%%-------------------------------------------------------------------
-spec list_by_user(UserId :: binary()) -> [#calendar_follow{}].
list_by_user(UserId) ->
mnesia:dirty_match_object(#calendar_follow{user_id = UserId, _ = '_'}).
%%%-------------------------------------------------------------------
%%% @doc Все follow календаря.
%%% @end
%%%-------------------------------------------------------------------
-spec list_by_calendar(CalendarId :: binary()) -> [#calendar_follow{}].
list_by_calendar(CalendarId) ->
mnesia:dirty_match_object(#calendar_follow{calendar_id = CalendarId, _ = '_'}).
%%%-------------------------------------------------------------------
%%% @doc Удалить все follow календаря (при удалении calendar).
%%% @end
%%%-------------------------------------------------------------------
-spec delete_by_calendar(CalendarId :: binary()) -> ok.
delete_by_calendar(CalendarId) ->
F = fun() ->
lists:foreach(
fun(#calendar_follow{id = Id}) ->
mnesia:delete({calendar_follow, Id})
end,
mnesia:match_object(#calendar_follow{calendar_id = CalendarId, _ = '_'})),
ok
end,
case mnesia:transaction(F) of
{atomic, ok} -> ok;
{aborted, Reason} -> error({delete_follows_failed, Reason})
end.
%%%===================================================================
%%% Internal
%%%===================================================================
find(CalendarId, UserId) ->
mnesia:match_object(#calendar_follow{calendar_id = CalendarId, user_id = UserId, _ = '_'}).