Current section

Files

Jump to
telega src telega@flow@storage.erl
Raw

src/telega@flow@storage.erl

-module(telega@flow@storage).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/telega/flow/storage.gleam").
-export([generate_id/3, create_ets_storage/0, create_noop_storage/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(" Storage utilities for flow persistence.\n").
-file("src/telega/flow/storage.gleam", 12).
?DOC(" Generate a flow instance ID from user, chat, and flow name\n").
-spec generate_id(integer(), integer(), binary()) -> binary().
generate_id(User_id, Chat_id, Flow_name) ->
<<<<<<<<Flow_name/binary, "_"/utf8>>/binary,
(erlang:integer_to_binary(Chat_id))/binary>>/binary,
"_"/utf8>>/binary,
(erlang:integer_to_binary(User_id))/binary>>.
-file("src/telega/flow/storage.gleam", 16).
-spec user_index_key(integer(), integer()) -> binary().
user_index_key(User_id, Chat_id) ->
<<<<<<"_idx:"/utf8, (erlang:integer_to_binary(Chat_id))/binary>>/binary,
":"/utf8>>/binary,
(erlang:integer_to_binary(User_id))/binary>>.
-file("src/telega/flow/storage.gleam", 24).
?DOC(
" Create ETS-backed storage for flow instances.\n"
"\n"
" Data persists in memory for the lifetime of the VM but does NOT survive VM restarts.\n"
" For persistent storage across restarts, implement a custom `FlowStorage` with a database backend.\n"
).
-spec create_ets_storage() -> {ok, telega@flow@types:flow_storage(any())} |
{error, telega@error:telega_error()}.
create_ets_storage() ->
gleam@result:'try'(
telega@internal@flow_storage:start(),
fun(Storage) ->
{ok,
{flow_storage,
fun(Instance) ->
telega@internal@flow_storage:save(
Storage,
erlang:element(2, Instance),
Instance
),
Index_key = user_index_key(
erlang:element(4, Instance),
erlang:element(5, Instance)
),
telega@internal@flow_storage:add_to_index(
Storage,
Index_key,
erlang:element(2, Instance)
),
{ok, nil}
end,
fun(Id) ->
{ok, telega@internal@flow_storage:load(Storage, Id)}
end,
fun(Id@1) ->
Instance@1 = telega@internal@flow_storage:load(
Storage,
Id@1
),
telega@internal@flow_storage:delete(Storage, Id@1),
case Instance@1 of
{some, Inst} ->
Index_key@1 = user_index_key(
erlang:element(4, Inst),
erlang:element(5, Inst)
),
telega@internal@flow_storage:remove_from_index(
Storage,
Index_key@1,
Id@1
);
none ->
nil
end,
{ok, nil}
end,
fun(User_id, Chat_id) ->
Index_key@2 = user_index_key(User_id, Chat_id),
Instance_ids = telega@internal@flow_storage:lookup_index(
Storage,
Index_key@2
),
{ok,
gleam@list:filter_map(
Instance_ids,
fun(Id@2) ->
case telega@internal@flow_storage:load(
Storage,
Id@2
) of
{some, Instance@2} ->
{ok, Instance@2};
none ->
{error, nil}
end
end
)}
end}}
end
).
-file("src/telega/flow/storage.gleam", 65).
?DOC(
" Create no-op storage that discards all data.\n"
" Useful for testing or stateless flows that don't need persistence.\n"
).
-spec create_noop_storage() -> telega@flow@types:flow_storage(any()).
create_noop_storage() ->
{flow_storage,
fun(_) -> {ok, nil} end,
fun(_) -> {ok, none} end,
fun(_) -> {ok, nil} end,
fun(_, _) -> {ok, []} end}.