-module(process_file). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/process_file.gleam"). -export([start/0, supervised/0, register/2]). -export_type([process_file_manager/0, message/0, state/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. -opaque process_file_manager() :: {process_file_manager, mala:bag_table(gleam@erlang@process:pid_(), binary()), gleam@erlang@process:subject(message())}. -opaque message() :: {registration, binary(), gleam@erlang@process:subject(nil)} | {monitored_process_down, gleam@erlang@process:pid_()}. -type state() :: {state, mala:bag_table(gleam@erlang@process:pid_(), binary())}. -file("src/process_file.gleam", 88). -spec handle_registration(state(), binary(), gleam@erlang@process:subject(nil)) -> gleam@otp@actor:next(state(), message()). handle_registration(State, Path, Reply) -> Pid@1 = case gleam@erlang@process:subject_owner(Reply) of {ok, Pid} -> Pid; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"registee must be alive"/utf8>>, file => <>, module => <<"process_file"/utf8>>, function => <<"handle_registration"/utf8>>, line => 94, value => _assert_fail, start => 2919, 'end' => 2968, pattern_start => 2930, pattern_end => 2937}) end, _ = gleam@erlang@process:monitor(Pid@1), case mala_ffi:bag_insert(erlang:element(2, State), Pid@1, Path) of {ok, _} -> nil; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"ETS table exists"/utf8>>, file => <>, module => <<"process_file"/utf8>>, function => <<"handle_registration"/utf8>>, line => 100, value => _assert_fail@1, start => 3229, 'end' => 3283, pattern_start => 3240, pattern_end => 3245}) end, gleam@erlang@process:send(Reply, nil), gleam@otp@actor:continue(State). -file("src/process_file.gleam", 109). -spec handle_monitored_process_down(state(), gleam@erlang@process:pid_()) -> gleam@otp@actor:next(state(), message()). handle_monitored_process_down(State, Pid) -> Table = erlang:element(2, State), Files@1 = case mala_ffi:bag_get(Table, Pid) of {ok, Files} -> Files; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"ETS table exists"/utf8>>, file => <>, module => <<"process_file"/utf8>>, function => <<"handle_monitored_process_down"/utf8>>, line => 115, value => _assert_fail, start => 3626, 'end' => 3669, pattern_start => 3637, pattern_end => 3646}) end, case mala_ffi:bag_delete_key(Table, Pid) of {ok, _} -> nil; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"ETS table exists"/utf8>>, file => <>, module => <<"process_file"/utf8>>, function => <<"handle_monitored_process_down"/utf8>>, line => 116, value => _assert_fail@1, start => 3694, 'end' => 3740, pattern_start => 3705, pattern_end => 3710}) end, case simplifile:delete_all(Files@1) of {ok, _} -> nil; _assert_fail@2 -> erlang:error(#{gleam_error => let_assert, message => <<"deletion must succeed"/utf8>>, file => <>, module => <<"process_file"/utf8>>, function => <<"handle_monitored_process_down"/utf8>>, line => 120, value => _assert_fail@2, start => 3922, 'end' => 3969, pattern_start => 3933, pattern_end => 3938}) end, gleam@otp@actor:continue(State). -file("src/process_file.gleam", 78). -spec handle_message(state(), message()) -> gleam@otp@actor:next(state(), message()). handle_message(State, Message) -> case Message of {monitored_process_down, Pid} -> handle_monitored_process_down(State, Pid); {registration, Path, Reply} -> handle_registration(State, Path, Reply) end. -file("src/process_file.gleam", 142). -spec convert_down_message(gleam@erlang@process:down()) -> message(). convert_down_message(Down) -> Pid@1 = case Down of {process_down, _, Pid, _} -> Pid; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"process_file manager actor should never be monitoring a port"/utf8>>, file => <>, module => <<"process_file"/utf8>>, function => <<"convert_down_message"/utf8>>, line => 143, value => _assert_fail, start => 4534, 'end' => 4581, pattern_start => 4545, pattern_end => 4574}) end, {monitored_process_down, Pid@1}. -file("src/process_file.gleam", 126). -spec initialise(gleam@erlang@process:subject(message())) -> {ok, gleam@otp@actor:initialised(state(), message(), process_file_manager())} | {error, any()}. initialise(Subject) -> Table = mala:new(), Handle = {process_file_manager, Table, Subject}, Selector = begin _pipe = gleam_erlang_ffi:new_selector(), _pipe@1 = gleam@erlang@process:select(_pipe, Subject), gleam@erlang@process:select_monitors( _pipe@1, fun convert_down_message/1 ) end, _pipe@2 = gleam@otp@actor:initialised({state, Table}), _pipe@3 = gleam@otp@actor:selecting(_pipe@2, Selector), _pipe@4 = gleam@otp@actor:returning(_pipe@3, Handle), {ok, _pipe@4}. -file("src/process_file.gleam", 24). ?DOC( " Create a new process file manager. Typically you should use the\n" " `supervised` function instead of this one, adding it to your application's\n" " supervision tree.\n" ). -spec start() -> {ok, gleam@otp@actor:started(process_file_manager())} | {error, gleam@otp@actor:start_error()}. start() -> _pipe = gleam@otp@actor:new_with_initialiser(1000, fun initialise/1), _pipe@1 = gleam@otp@actor:on_message(_pipe, fun handle_message/2), gleam@otp@actor:start(_pipe@1). -file("src/process_file.gleam", 32). ?DOC(" A supervision specification for a new process file manager.\n"). -spec supervised() -> gleam@otp@supervision:child_specification(process_file_manager()). supervised() -> gleam@otp@supervision:worker(fun start/0). -file("src/process_file.gleam", 45). ?DOC( " Register a file system path as being owned by the process that calls this\n" " function, so when the process exits the process file manager will delete\n" " any file or directory at the path. If there is no file at that location\n" " then nothing happens.\n" "\n" " The first time a process calls this function they will be registered by the\n" " manager process, but subsequent calls work directly with ETS and do not\n" " produce any work for the manager.\n" ). -spec register(process_file_manager(), binary()) -> {ok, nil} | {error, nil}. register(Manager, New_path) -> Owner = erlang:self(), Table = erlang:element(2, Manager), gleam@result:'try'( mala_ffi:bag_has_key(Table, Owner), fun(Already_registered) -> case Already_registered of true -> mala_ffi:bag_insert(Table, Owner, New_path); false -> {ok, gleam@otp@actor:call( erlang:element(3, Manager), 1000, fun(_capture) -> {registration, New_path, _capture} end )} end end ).