Current section

Files

Jump to
glixir src glixir@genserver.erl
Raw

src/glixir@genserver.erl

-module(glixir@genserver).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-define(FILEPATH, "src/glixir/genserver.gleam").
-export([start_link/2, start_link_named/3, call_timeout/3, call/2, cast/2, pid/1, lookup_name/1, call_named/2, cast_named/2, stop/1]).
-export_type([gen_server/0, gen_server_error/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(
" Type-safe GenServer interop for Gleam\n"
" \n"
" This module provides a safe interface to Elixir GenServers from Gleam.\n"
).
-opaque gen_server() :: {gen_server, gleam@erlang@process:pid_()}.
-type gen_server_error() :: {start_error, binary()} |
call_timeout |
{call_error, binary()} |
{cast_error, binary()} |
{not_found, binary()}.
-file("src/glixir/genserver.gleam", 53).
?DOC(" Start a GenServer using Module.start_link/1\n").
-spec start_link(binary(), any()) -> {ok, gen_server()} |
{error, gen_server_error()}.
start_link(Module, Args) ->
logging:log(
debug,
<<<<"🔍 GenServer.start_link called with module: '"/utf8, Module/binary>>/binary,
"'"/utf8>>
),
Final_module_name = case gleam_stdlib:string_starts_with(
Module,
<<"Elixir."/utf8>>
) of
true ->
logging:log(
debug,
<<"✅ Module already has Elixir. prefix: "/utf8, Module/binary>>
),
Module;
false ->
Prefixed = <<"Elixir."/utf8, Module/binary>>,
logging:log(
debug,
<<<<<<"➕ Adding Elixir. prefix: "/utf8, Module/binary>>/binary,
" → "/utf8>>/binary,
Prefixed/binary>>
),
Prefixed
end,
logging:log(
debug,
<<"🚀 Calling FFI start_genserver with module: "/utf8,
Final_module_name/binary>>
),
case glixir_ffi:start_genserver(Final_module_name, Args) of
{ok, Pid} ->
logging:log(
info,
<<"✅ GenServer started successfully: "/utf8,
(gleam@string:inspect(Pid))/binary>>
),
{ok, {gen_server, Pid}};
{error, Reason} ->
logging:log(
error,
<<"❌ GenServer start failed: "/utf8,
(gleam@string:inspect(Reason))/binary>>
),
{error, {start_error, gleam@string:inspect(Reason)}}
end.
-file("src/glixir/genserver.gleam", 101).
?DOC(" Start a GenServer with a registered name\n").
-spec start_link_named(binary(), binary(), any()) -> {ok, gen_server()} |
{error, gen_server_error()}.
start_link_named(Module, Name, Args) ->
logging:log(
debug,
<<<<<<<<"🔍 GenServer.start_link_named called with module: '"/utf8,
Module/binary>>/binary,
"', name: '"/utf8>>/binary,
Name/binary>>/binary,
"'"/utf8>>
),
Final_module_name = case gleam_stdlib:string_starts_with(
Module,
<<"Elixir."/utf8>>
) of
true ->
logging:log(
debug,
<<"✅ Module already has Elixir. prefix: "/utf8, Module/binary>>
),
Module;
false ->
Prefixed = <<"Elixir."/utf8, Module/binary>>,
logging:log(
debug,
<<<<<<"➕ Adding Elixir. prefix: "/utf8, Module/binary>>/binary,
" → "/utf8>>/binary,
Prefixed/binary>>
),
Prefixed
end,
logging:log(
debug,
<<<<<<"🚀 Calling FFI start_genserver_named with module: "/utf8,
Final_module_name/binary>>/binary,
", name: "/utf8>>/binary,
Name/binary>>
),
case glixir_ffi:start_genserver_named(Final_module_name, Name, Args) of
{ok, Pid} ->
logging:log(
info,
<<<<<<"✅ Named GenServer '"/utf8, Name/binary>>/binary,
"' started successfully: "/utf8>>/binary,
(gleam@string:inspect(Pid))/binary>>
),
{ok, {gen_server, Pid}};
{error, Reason} ->
logging:log(
error,
<<<<<<"❌ Named GenServer '"/utf8, Name/binary>>/binary,
"' start failed: "/utf8>>/binary,
(gleam@string:inspect(Reason))/binary>>
),
{error, {start_error, gleam@string:inspect(Reason)}}
end.
-file("src/glixir/genserver.gleam", 175).
?DOC(" Send a synchronous call with custom timeout\n").
-spec call_timeout(gen_server(), any(), integer()) -> {ok, any()} |
{error, gen_server_error()}.
call_timeout(Server, Request, Timeout) ->
{gen_server, Pid} = Server,
logging:log(
debug,
<<<<<<"📞⏱️ GenServer.call_timeout to PID "/utf8,
(gleam@string:inspect(Pid))/binary>>/binary,
" with timeout "/utf8>>/binary,
(gleam@string:inspect(Timeout))/binary>>
),
logging:log(
debug,
<<"📞⏱️ Request: "/utf8, (gleam@string:inspect(Request))/binary>>
),
Response = gen_server:call(Pid, Request, Timeout),
logging:log(
debug,
<<"📞✅ GenServer call response: "/utf8,
(gleam@string:inspect(Response))/binary>>
),
{ok, gleam_stdlib:identity(Response)}.
-file("src/glixir/genserver.gleam", 166).
?DOC(" Send a synchronous call to the GenServer (5s timeout)\n").
-spec call(gen_server(), any()) -> {ok, any()} | {error, gen_server_error()}.
call(Server, Request) ->
logging:log(
debug,
<<"📞 GenServer.call with request: "/utf8,
(gleam@string:inspect(Request))/binary>>
),
call_timeout(Server, Request, 5000).
-file("src/glixir/genserver.gleam", 227).
?DOC(" Send an asynchronous cast to the GenServer\n").
-spec cast(gen_server(), any()) -> {ok, nil} | {error, gen_server_error()}.
cast(Server, Request) ->
{gen_server, Pid} = Server,
logging:log(
debug,
<<<<<<"📨 GenServer.cast to PID "/utf8,
(gleam@string:inspect(Pid))/binary>>/binary,
" with request: "/utf8>>/binary,
(gleam@string:inspect(Request))/binary>>
),
Result = gen_server:cast(Pid, Request),
logging:log(
debug,
<<"📨✅ GenServer cast result: "/utf8,
(gleam@string:inspect(Result))/binary>>
),
case erlang:atom_to_binary(Result) of
<<"ok"/utf8>> ->
logging:log(debug, <<"📨✅ Cast successful"/utf8>>),
{ok, nil};
Other ->
logging:log(error, <<"📨❌ Cast failed with: "/utf8, Other/binary>>),
{error, {cast_error, Other}}
end.
-file("src/glixir/genserver.gleam", 281).
?DOC(" Get the PID of a GenServer\n").
-spec pid(gen_server()) -> gleam@erlang@process:pid_().
pid(Server) ->
{gen_server, P} = Server,
logging:log(
debug,
<<"🆔 GenServer.pid returning: "/utf8, (gleam@string:inspect(P))/binary>>
),
P.
-file("src/glixir/genserver.gleam", 288).
?DOC(" Look up a GenServer by registered name\n").
-spec lookup_name(binary()) -> {ok, gen_server()} | {error, gen_server_error()}.
lookup_name(Name) ->
logging:log(
debug,
<<<<"🔍 GenServer.lookup_name for: '"/utf8, Name/binary>>/binary,
"'"/utf8>>
),
Name_atom = erlang:binary_to_atom(Name),
logging:log(
debug,
<<"🔍 Created lookup atom: "/utf8,
(gleam@string:inspect(Name_atom))/binary>>
),
Pid_result = erlang:whereis(Name_atom),
logging:log(
debug,
<<"🔍 whereis result: "/utf8, (gleam@string:inspect(Pid_result))/binary>>
),
case gleam_stdlib:classify_dynamic(Pid_result) of
<<"Pid"/utf8>> ->
logging:log(
info,
<<<<"🔍✅ Found GenServer PID for '"/utf8, Name/binary>>/binary,
"'"/utf8>>
),
{ok, {gen_server, gleam_stdlib:identity(Pid_result)}};
<<"Atom"/utf8>> ->
logging:log(
warning,
<<<<"🔍❌ GenServer '"/utf8, Name/binary>>/binary,
"' returned atom (likely 'undefined')"/utf8>>
),
{error, {not_found, Name}};
Other ->
logging:log(
warning,
<<<<<<"🔍❌ GenServer '"/utf8, Name/binary>>/binary,
"' not found, got type: "/utf8>>/binary,
Other/binary>>
),
{error, {not_found, Name}}
end.
-file("src/glixir/genserver.gleam", 202).
?DOC(" Call a named GenServer\n").
-spec call_named(binary(), any()) -> {ok, any()} | {error, gen_server_error()}.
call_named(Name, Request) ->
logging:log(
debug,
<<<<<<"📞🏷️ GenServer.call_named to '"/utf8, Name/binary>>/binary,
"' with request: "/utf8>>/binary,
(gleam@string:inspect(Request))/binary>>
),
case lookup_name(Name) of
{ok, Server} ->
logging:log(
debug,
<<"📞🏷️✅ Found named GenServer, making call"/utf8>>
),
call(Server, Request);
{error, E} ->
logging:log(
error,
<<"📞🏷️❌ Named GenServer lookup failed: "/utf8,
(gleam@string:inspect(E))/binary>>
),
{error, E}
end.
-file("src/glixir/genserver.gleam", 256).
?DOC(" Cast to a named GenServer\n").
-spec cast_named(binary(), any()) -> {ok, nil} | {error, gen_server_error()}.
cast_named(Name, Request) ->
logging:log(
debug,
<<<<<<"📨🏷️ GenServer.cast_named to '"/utf8, Name/binary>>/binary,
"' with request: "/utf8>>/binary,
(gleam@string:inspect(Request))/binary>>
),
case lookup_name(Name) of
{ok, Server} ->
logging:log(
debug,
<<"📨🏷️✅ Found named GenServer, making cast"/utf8>>
),
cast(Server, Request);
{error, E} ->
logging:log(
error,
<<"📨🏷️❌ Named GenServer lookup failed: "/utf8,
(gleam@string:inspect(E))/binary>>
),
{error, E}
end.
-file("src/glixir/genserver.gleam", 323).
?DOC(" Stop a GenServer gracefully\n").
-spec stop(gen_server()) -> {ok, nil} | {error, gen_server_error()}.
stop(Server) ->
logging:log(debug, <<"🛑 GenServer.stop called"/utf8>>),
cast(Server, erlang:binary_to_atom(<<"stop"/utf8>>)).