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
This commit is contained in:
128
fluxer/fluxer_gateway/src/guild/guild_counts_cache.erl
Normal file
128
fluxer/fluxer_gateway/src/guild/guild_counts_cache.erl
Normal file
@@ -0,0 +1,128 @@
|
||||
%% 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.
|
||||
Reference in New Issue
Block a user