Files
fx-test/fluxer/fluxer_gateway/src/guild/guild_counts_cache.erl
Vish 3b9d759b4b feat: add fluxer upstream source and self-hosting documentation
- Clone of github.com/fluxerapp/fluxer (official upstream)
- SELF_HOSTING.md: full VM rebuild procedure, architecture overview,
  service reference, step-by-step setup, troubleshooting, seattle reference
- dev/.env.example: all env vars with secrets redacted and generation instructions
- dev/livekit.yaml: LiveKit config template with placeholder keys
- fluxer-seattle/: existing seattle deployment setup scripts
2026-03-13 00:55:14 -07:00

129 lines
3.2 KiB
Erlang

%% Copyright (C) 2026 Fluxer Contributors
%%
%% This file is part of Fluxer.
%%
%% Fluxer is free software: you can redistribute it and/or modify
%% it under the terms of the GNU Affero General Public License as published by
%% the Free Software Foundation, either version 3 of the License, or
%% (at your option) any later version.
%%
%% Fluxer is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
%% GNU Affero General Public License for more details.
%%
%% You should have received a copy of the GNU Affero General Public License
%% along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
-module(guild_counts_cache).
-export([
init/0,
update/3,
get/1,
delete/1
]).
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
-endif.
-define(TABLE, guild_counts_cache).
-type guild_id() :: integer().
-spec init() -> ok.
init() ->
case ets:whereis(?TABLE) of
undefined ->
_ = ets:new(?TABLE, [
named_table,
public,
set,
{read_concurrency, true},
{write_concurrency, true}
]),
ok;
_ ->
ok
end.
-spec update(guild_id(), non_neg_integer(), non_neg_integer()) -> ok.
update(GuildId, MemberCount, OnlineCount) ->
ensure_table(),
ets:insert(?TABLE, {GuildId, MemberCount, OnlineCount}),
ok.
-spec get(guild_id()) -> {ok, non_neg_integer(), non_neg_integer()} | miss.
get(GuildId) ->
case catch ets:lookup(?TABLE, GuildId) of
[{GuildId, MemberCount, OnlineCount}] ->
{ok, MemberCount, OnlineCount};
_ ->
miss
end.
-spec delete(guild_id()) -> ok.
delete(GuildId) ->
catch ets:delete(?TABLE, GuildId),
ok.
-spec ensure_table() -> ok.
ensure_table() ->
case ets:whereis(?TABLE) of
undefined -> init();
_ -> ok
end.
-ifdef(TEST).
init_creates_table_test() ->
catch ets:delete(?TABLE),
ok = init(),
?assertNotEqual(undefined, ets:whereis(?TABLE)),
catch ets:delete(?TABLE).
init_idempotent_test() ->
catch ets:delete(?TABLE),
ok = init(),
ok = init(),
?assertNotEqual(undefined, ets:whereis(?TABLE)),
catch ets:delete(?TABLE).
update_and_get_test() ->
catch ets:delete(?TABLE),
ok = init(),
ok = update(100, 50, 25),
?assertEqual({ok, 50, 25}, guild_counts_cache:get(100)),
catch ets:delete(?TABLE).
get_miss_test() ->
catch ets:delete(?TABLE),
ok = init(),
?assertEqual(miss, guild_counts_cache:get(999)),
catch ets:delete(?TABLE).
update_overwrites_test() ->
catch ets:delete(?TABLE),
ok = init(),
ok = update(100, 50, 25),
ok = update(100, 60, 30),
?assertEqual({ok, 60, 30}, guild_counts_cache:get(100)),
catch ets:delete(?TABLE).
delete_removes_entry_test() ->
catch ets:delete(?TABLE),
ok = init(),
ok = update(100, 50, 25),
ok = delete(100),
?assertEqual(miss, guild_counts_cache:get(100)),
catch ets:delete(?TABLE).
delete_nonexistent_test() ->
catch ets:delete(?TABLE),
ok = init(),
ok = delete(999),
catch ets:delete(?TABLE).
-endif.