Current section

Files

Jump to
sprocket src sprocket@runtime.erl
Raw

src/sprocket@runtime.erl

-module(sprocket@runtime).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-define(FILEPATH, "src/sprocket/runtime.gleam").
-export([stop/1, get_reconciled/1, handle_client_message/2, process_client_message_immediate/4, render_update/1, reconcile_immediate/1, start/2]).
-export_type([runtime_message/0, client_message/0, state/0, message/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(false).
-type runtime_message() :: {full_update,
sprocket@internal@reconcile:reconciled_element()} |
{patch_update, sprocket@internal@patch:patch()} |
{outbound_client_hook_event,
binary(),
binary(),
binary(),
gleam@option:option(gleam@dynamic:dynamic_())}.
-type client_message() :: {client_event,
binary(),
binary(),
gleam@dynamic:dynamic_()} |
{inbound_client_hook_event,
binary(),
binary(),
binary(),
gleam@dynamic:dynamic_()}.
-opaque state() :: {state,
sprocket@internal@context:context(),
gleam@option:option(sprocket@internal@reconcile:reconciled_element()),
gleam@erlang@process:subject(sprocket@internal@utils@cuid:message()),
fun((runtime_message()) -> {ok, nil} | {error, nil})}.
-opaque message() :: shutdown |
{get_reconciled,
gleam@erlang@process:subject(gleam@option:option(sprocket@internal@reconcile:reconciled_element()))} |
{process_client_message,
sprocket@internal@utils@unique:unique(sprocket@internal@context:element_id()),
binary(),
gleam@dynamic:dynamic_()} |
{process_client_message_immediate,
gleam@erlang@process:subject({ok, nil} | {error, nil}),
sprocket@internal@utils@unique:unique(sprocket@internal@context:element_id()),
binary(),
gleam@dynamic:dynamic_()} |
{process_client_hook_event,
sprocket@internal@utils@unique:unique(sprocket@internal@context:element_id()),
binary(),
binary(),
gleam@dynamic:dynamic_()} |
{update_hook_state,
sprocket@internal@utils@unique:unique(sprocket@internal@context:hook_id()),
fun((sprocket@internal@context:hook()) -> sprocket@internal@context:hook())} |
{dispatch_client_hook_event,
sprocket@internal@utils@unique:unique(sprocket@internal@context:hook_id()),
binary(),
gleam@option:option(gleam@dynamic:dynamic_())} |
{reconcile_immediate,
gleam@erlang@process:subject(sprocket@internal@reconcile:reconciled_element())} |
render_update.
-file("src/sprocket/runtime.gleam", 371).
?DOC(false).
-spec stop(gleam@erlang@process:subject(message())) -> nil.
stop(Actor) ->
sprocket@internal@logger:debug(<<"actor.send Shutdown"/utf8>>),
gleam@otp@actor:send(Actor, shutdown).
-file("src/sprocket/runtime.gleam", 378).
?DOC(false).
-spec get_reconciled(gleam@erlang@process:subject(message())) -> gleam@option:option(sprocket@internal@reconcile:reconciled_element()).
get_reconciled(Actor) ->
sprocket@internal@logger:debug(<<"process.call GetReconciled"/utf8>>),
gleam@erlang@process:call(
Actor,
1000,
fun(Field@0) -> {get_reconciled, Field@0} end
).
-file("src/sprocket/runtime.gleam", 385).
?DOC(false).
-spec handle_client_message(
gleam@erlang@process:subject(message()),
client_message()
) -> nil.
handle_client_message(Actor, Msg) ->
case Msg of
{client_event, Element_id, Kind, Payload} ->
sprocket@internal@logger:debug(
<<"process.call ProcessClientMessage"/utf8>>
),
gleam@otp@actor:send(
Actor,
{process_client_message,
sprocket@internal@utils@unique:from_string(Element_id),
Kind,
Payload}
);
{inbound_client_hook_event, Element_id@1, Hook, Kind@1, Payload@1} ->
sprocket@internal@logger:debug(
<<"actor.send ProcessClientHookEvent"/utf8>>
),
gleam@otp@actor:send(
Actor,
{process_client_hook_event,
sprocket@internal@utils@unique:from_string(Element_id@1),
Hook,
Kind@1,
Payload@1}
)
end.
-file("src/sprocket/runtime.gleam", 411).
?DOC(false).
-spec process_client_message_immediate(
gleam@erlang@process:subject(message()),
binary(),
binary(),
gleam@dynamic:dynamic_()
) -> {ok, nil} | {error, nil}.
process_client_message_immediate(Actor, Element_id, Kind, Payload) ->
sprocket@internal@logger:debug(
<<"process.call ProcessClientMessageImmediate"/utf8>>
),
gleam@erlang@process:call(
Actor,
1000,
fun(_capture) ->
{process_client_message_immediate,
_capture,
sprocket@internal@utils@unique:from_string(Element_id),
Kind,
Payload}
end
).
-file("src/sprocket/runtime.gleam", 427).
?DOC(false).
-spec render_update(gleam@erlang@process:subject(message())) -> nil.
render_update(Actor) ->
sprocket@internal@logger:debug(<<"actor.send RenderUpdate"/utf8>>),
gleam@otp@actor:send(Actor, render_update).
-file("src/sprocket/runtime.gleam", 434).
?DOC(false).
-spec reconcile_immediate(gleam@erlang@process:subject(message())) -> sprocket@internal@reconcile:reconciled_element().
reconcile_immediate(Actor) ->
sprocket@internal@logger:debug(<<"process.try_call Reconcile"/utf8>>),
gleam@erlang@process:call(
Actor,
1000,
fun(Field@0) -> {reconcile_immediate, Field@0} end
).
-file("src/sprocket/runtime.gleam", 514).
?DOC(false).
-spec build_hooks_map(
sprocket@internal@reconcile:reconciled_element(),
gleam@dict:dict(sprocket@internal@utils@unique:unique(sprocket@internal@context:hook_id()), sprocket@internal@context:hook())
) -> gleam@dict:dict(sprocket@internal@utils@unique:unique(sprocket@internal@context:hook_id()), sprocket@internal@context:hook()).
build_hooks_map(Node, Acc) ->
case Node of
{reconciled_component, _, _, _, Hooks, El} ->
Acc@2 = sprocket@internal@utils@ordered_map:fold(
Hooks,
Acc,
fun(Acc@1, Hook) ->
{keyed_item, _, Hook@1} = Hook,
case Hook@1 of
{callback, Id, _, _} ->
gleam@dict:insert(Acc@1, Id, Hook@1);
{memo, Id@1, _, _} ->
gleam@dict:insert(Acc@1, Id@1, Hook@1);
{effect, Id@2, _, _, _} ->
gleam@dict:insert(Acc@1, Id@2, Hook@1);
{state, Id@3, _} ->
gleam@dict:insert(Acc@1, Id@3, Hook@1);
{reducer, Id@4, _, _} ->
gleam@dict:insert(Acc@1, Id@4, Hook@1);
{client, Id@5, _, _} ->
gleam@dict:insert(Acc@1, Id@5, Hook@1)
end
end
),
build_hooks_map(El, Acc@2);
{reconciled_element, _, _, _, _, Children} ->
gleam@list:fold(
Children,
Acc,
fun(Acc@3, Child) ->
maps:merge(Acc@3, build_hooks_map(Child, Acc@3))
end
);
{reconciled_fragment, _, Children@1} ->
gleam@list:fold(
Children@1,
Acc,
fun(Acc@4, Child@1) ->
maps:merge(Acc@4, build_hooks_map(Child@1, Acc@4))
end
);
_ ->
Acc
end.
-file("src/sprocket/runtime.gleam", 464).
?DOC(false).
-spec cleanup_hooks(sprocket@internal@reconcile:reconciled_element()) -> nil.
cleanup_hooks(Rendered) ->
_pipe = build_hooks_map(Rendered, maps:new()),
_pipe@1 = maps:values(_pipe),
gleam@list:each(_pipe@1, fun(Hook) -> case Hook of
{effect, _, _, _, Prev} ->
case Prev of
{some, {effect_result, {some, Cleanup}, _}} ->
Cleanup();
_ ->
nil
end;
{reducer, _, _, Cleanup@1} ->
Cleanup@1();
_ ->
nil
end end).
-file("src/sprocket/runtime.gleam", 484).
?DOC(false).
-spec run_cleanup_for_disposed_hooks(
sprocket@internal@reconcile:reconciled_element(),
sprocket@internal@reconcile:reconciled_element()
) -> nil.
run_cleanup_for_disposed_hooks(Prev_rendered, Rendered) ->
Prev_hooks = build_hooks_map(Prev_rendered, maps:new()),
New_hooks = build_hooks_map(Rendered, maps:new()),
Removed_hooks = begin
_pipe = Prev_hooks,
_pipe@1 = maps:keys(_pipe),
gleam@list:filter(
_pipe@1,
fun(Id) -> not gleam@dict:has_key(New_hooks, Id) end
)
end,
_pipe@2 = Removed_hooks,
gleam@list:each(
_pipe@2,
fun(Id@1) -> case gleam_stdlib:map_get(Prev_hooks, Id@1) of
{ok, {effect, _, _, _, Prev}} ->
case Prev of
{some, {effect_result, {some, Cleanup}, _}} ->
Cleanup();
_ ->
nil
end;
{ok, {reducer, _, _, Cleanup@1}} ->
Cleanup@1();
_ ->
nil
end end
).
-file("src/sprocket/runtime.gleam", 603).
?DOC(false).
-spec maybe_cleanup_and_rerun_effect(
gleam@option:option(fun(() -> nil)),
fun(() -> gleam@option:option(fun(() -> nil))),
gleam@option:option(list(gleam@dynamic:dynamic_()))
) -> sprocket@internal@context:effect_result().
maybe_cleanup_and_rerun_effect(Cleanup, Effect_fn, Deps) ->
case Cleanup of
{some, Cleanup_fn} ->
Cleanup_fn(),
{effect_result, Effect_fn(), Deps};
_ ->
{effect_result, Effect_fn(), Deps}
end.
-file("src/sprocket/runtime.gleam", 579).
?DOC(false).
-spec run_effect(
fun(() -> gleam@option:option(fun(() -> nil))),
list(gleam@dynamic:dynamic_()),
gleam@option:option(sprocket@internal@context:effect_result())
) -> sprocket@internal@context:effect_result().
run_effect(Effect_fn, Deps, Prev) ->
case Prev of
{some, {effect_result, Cleanup, {some, Prev_deps}}} ->
case sprocket@internal@context:compare_deps(Prev_deps, Deps) of
{changed, _} ->
maybe_cleanup_and_rerun_effect(
Cleanup,
Effect_fn,
{some, Deps}
);
unchanged ->
{effect_result, Cleanup, {some, Deps}}
end;
none ->
maybe_cleanup_and_rerun_effect(none, Effect_fn, {some, Deps});
_ ->
sprocket@internal@exceptions:throw_on_unexpected_hook_result(
{<<"handle_effect"/utf8>>, Prev}
)
end.
-file("src/sprocket/runtime.gleam", 641).
?DOC(false).
-spec find_reconciled_hook(
sprocket@internal@reconcile:reconciled_element(),
fun((sprocket@internal@context:hook()) -> boolean())
) -> gleam@option:option(sprocket@internal@context:hook()).
find_reconciled_hook(Node, Find_by) ->
case Node of
{reconciled_component, _, _, _, Hooks, El} ->
case sprocket@internal@utils@ordered_map:find(
Hooks,
fun(Keyed_item) -> Find_by(erlang:element(3, Keyed_item)) end
) of
{ok, {keyed_item, _, Hook}} ->
{some, Hook};
_ ->
find_reconciled_hook(El, Find_by)
end;
{reconciled_element, _, _, _, _, Children} ->
gleam@list:fold(Children, none, fun(Acc, Child) -> case Acc of
{some, _} ->
Acc;
_ ->
find_reconciled_hook(Child, Find_by)
end end);
{reconciled_fragment, _, Children@1} ->
gleam@list:fold(
Children@1,
none,
fun(Acc@1, Child@1) -> case Acc@1 of
{some, _} ->
Acc@1;
_ ->
find_reconciled_hook(Child@1, Find_by)
end end
);
_ ->
none
end.
-file("src/sprocket/runtime.gleam", 721).
?DOC(false).
-spec process_next_hook(
sprocket@internal@utils@ordered_map:ordered_map_iter(integer(), sprocket@internal@context:hook()),
{list(sprocket@internal@utils@ordered_map:keyed_item(integer(), sprocket@internal@context:hook())),
gleam@dict:dict(integer(), sprocket@internal@context:hook()),
integer()},
fun((sprocket@internal@context:hook()) -> sprocket@internal@context:hook())
) -> {list(sprocket@internal@utils@ordered_map:keyed_item(integer(), sprocket@internal@context:hook())),
gleam@dict:dict(integer(), sprocket@internal@context:hook()),
integer()}.
process_next_hook(Iter, Acc, Process_hook) ->
case sprocket@internal@utils@ordered_map:next(Iter) of
{ok, {Iter@1, {keyed_item, Index, Hook}}} ->
{Ordered, By_index, Size} = Acc,
Updated = Process_hook(Hook),
process_next_hook(
Iter@1,
{[{keyed_item, Index, Updated} | Ordered],
gleam@dict:insert(By_index, Index, Updated),
Size + 1},
Process_hook
);
{error, _} ->
Acc
end.
-file("src/sprocket/runtime.gleam", 709).
?DOC(false).
-spec process_hooks(
sprocket@internal@utils@ordered_map:ordered_map(integer(), sprocket@internal@context:hook()),
fun((sprocket@internal@context:hook()) -> sprocket@internal@context:hook())
) -> sprocket@internal@utils@ordered_map:ordered_map(integer(), sprocket@internal@context:hook()).
process_hooks(Hooks, Process_hook) ->
{R_ordered, By_index, Size} = begin
_pipe = Hooks,
_pipe@1 = sprocket@internal@utils@ordered_map:iter(_pipe),
process_next_hook(_pipe@1, {[], maps:new(), 0}, Process_hook)
end,
sprocket@internal@utils@ordered_map:from(
lists:reverse(R_ordered),
By_index,
Size
).
-file("src/sprocket/runtime.gleam", 676).
?DOC(false).
-spec traverse_rendered_hooks(
sprocket@internal@reconcile:reconciled_element(),
fun((sprocket@internal@context:hook()) -> sprocket@internal@context:hook())
) -> sprocket@internal@reconcile:reconciled_element().
traverse_rendered_hooks(Node, Process_hook) ->
case Node of
{reconciled_component, Fc, Key, Props, Hooks, El} ->
Processed_hooks = process_hooks(Hooks, Process_hook),
{reconciled_component,
Fc,
Key,
Props,
Processed_hooks,
traverse_rendered_hooks(El, Process_hook)};
{reconciled_element, Id, Tag, Key@1, Hooks@1, Children} ->
R_children = gleam@list:fold(
Children,
[],
fun(Acc, Child) ->
[traverse_rendered_hooks(Child, Process_hook) | Acc]
end
),
{reconciled_element,
Id,
Tag,
Key@1,
Hooks@1,
lists:reverse(R_children)};
{reconciled_fragment, Key@2, Children@1} ->
R_children@1 = gleam@list:fold(
Children@1,
[],
fun(Acc@1, Child@1) ->
[traverse_rendered_hooks(Child@1, Process_hook) | Acc@1]
end
),
{reconciled_fragment, Key@2, lists:reverse(R_children@1)};
_ ->
Node
end.
-file("src/sprocket/runtime.gleam", 617).
?DOC(false).
-spec find_and_update_hook(
sprocket@internal@reconcile:reconciled_element(),
sprocket@internal@utils@unique:unique(sprocket@internal@context:hook_id()),
fun((sprocket@internal@context:hook()) -> sprocket@internal@context:hook())
) -> sprocket@internal@reconcile:reconciled_element().
find_and_update_hook(Reconciled, Hook_id, Update_fn) ->
traverse_rendered_hooks(
Reconciled,
fun(Hook) -> case sprocket@internal@context:has_id(Hook, Hook_id) of
true ->
Update_fn(Hook);
false ->
Hook
end end
).
-file("src/sprocket/runtime.gleam", 634).
?DOC(false).
-spec process_state_hooks(
sprocket@internal@reconcile:reconciled_element(),
fun((sprocket@internal@context:hook()) -> sprocket@internal@context:hook())
) -> sprocket@internal@reconcile:reconciled_element().
process_state_hooks(Rendered, Process_hook) ->
traverse_rendered_hooks(Rendered, Process_hook).
-file("src/sprocket/runtime.gleam", 565).
?DOC(false).
-spec run_effects(sprocket@internal@reconcile:reconciled_element()) -> sprocket@internal@reconcile:reconciled_element().
run_effects(Rendered) ->
process_state_hooks(Rendered, fun(Hook) -> case Hook of
{effect, Id, Effect_fn, Deps, Prev} ->
Result = run_effect(Effect_fn, Deps, Prev),
{effect, Id, Effect_fn, Deps, {some, Result}};
Other ->
Other
end end).
-file("src/sprocket/runtime.gleam", 440).
?DOC(false).
-spec do_reconciliation(
sprocket@internal@context:context(),
sprocket@internal@context:element(),
gleam@option:option(sprocket@internal@reconcile:reconciled_element())
) -> {sprocket@internal@context:context(),
sprocket@internal@reconcile:reconciled_element()}.
do_reconciliation(Ctx, El, Prev) ->
sprocket@internal@utils@timer:timed_operation(
<<"runtime.reconcile"/utf8>>,
fun() ->
{reconciled_result, Ctx@1, Reconciled} = begin
_pipe = Ctx,
_pipe@1 = sprocket@internal@context:prepare_for_reconciliation(
_pipe
),
sprocket@internal@reconcilers@recursive:reconcile(
_pipe@1,
El,
none,
Prev
)
end,
gleam@option:map(
Prev,
fun(Prev@1) ->
run_cleanup_for_disposed_hooks(Prev@1, Reconciled)
end
),
Reconciled@1 = run_effects(Reconciled),
{Ctx@1, Reconciled@1}
end
).
-file("src/sprocket/runtime.gleam", 100).
?DOC(false).
-spec handle_message(state(), message()) -> gleam@otp@actor:next(state(), message()).
handle_message(State, Message) ->
case Message of
shutdown ->
case erlang:element(3, State) of
{some, Reconciled} ->
cleanup_hooks(Reconciled),
nil;
_ ->
nil
end,
gleam@otp@actor:stop();
{get_reconciled, Reply_with} ->
gleam@otp@actor:send(Reply_with, erlang:element(3, State)),
gleam@otp@actor:continue(State);
{process_client_message, Element_id, Kind, Payload} ->
_ = begin
_pipe = gleam@list:find(
erlang:element(4, erlang:element(2, State)),
fun(H) ->
{event_handler, Handler_id, Handler_kind, _} = H,
(Handler_id =:= Element_id) andalso (Handler_kind =:= Kind)
end
),
_pipe@1 = gleam@result:map(
_pipe,
fun(H@1) ->
{event_handler, _, _, Handler_fn} = H@1,
Handler_fn(Payload)
end
),
gleam@result:map_error(
_pipe@1,
fun(_) ->
sprocket@internal@logger:error(
<<<<<<"No handler found for element "/utf8,
(sprocket@internal@utils@unique:to_string(
Element_id
))/binary>>/binary,
" and kind "/utf8>>/binary,
Kind/binary>>
)
end
)
end,
gleam@otp@actor:continue(State);
{process_client_message_immediate,
Reply_with@1,
Element_id@1,
Kind@1,
Payload@1} ->
Handler = gleam@list:find(
erlang:element(4, erlang:element(2, State)),
fun(H@2) ->
{event_handler, Handler_id@1, Handler_kind@1, _} = H@2,
(Handler_id@1 =:= Element_id@1) andalso (Handler_kind@1 =:= Kind@1)
end
),
case Handler of
{ok, {event_handler, _, _, Handler_fn@1}} ->
Handler_fn@1(Payload@1),
gleam@otp@actor:send(Reply_with@1, {ok, nil}),
gleam@otp@actor:continue(State);
_ ->
sprocket@internal@logger:error(
<<<<<<"No handler found for element "/utf8,
(sprocket@internal@utils@unique:to_string(
Element_id@1
))/binary>>/binary,
" and kind "/utf8>>/binary,
Kind@1/binary>>
),
gleam@otp@actor:send(Reply_with@1, {error, nil}),
gleam@otp@actor:continue(State)
end;
{process_client_hook_event, Element_id@2, Hook_name, Kind@2, Payload@2} ->
sprocket@internal@utils@common:require(
erlang:element(3, State),
fun() ->
sprocket@internal@logger:error(
<<"Runtime must be reconciled before processing client hooks"/utf8>>
),
gleam@otp@actor:continue(State)
end,
fun(Reconciled@1) ->
_ = begin
_pipe@2 = gleam@list:find(
erlang:element(5, erlang:element(2, State)),
fun(H@3) ->
(erlang:element(2, H@3) =:= Element_id@2)
andalso (erlang:element(3, H@3) =:= Hook_name)
end
),
gleam@result:map(
_pipe@2,
fun(H@4) ->
_pipe@3 = find_reconciled_hook(
Reconciled@1,
fun(Hook) -> case Hook of
{client, Hook_id, _, _} ->
Hook_id =:= erlang:element(
4,
H@4
);
_ ->
false
end end
),
gleam@option:map(
_pipe@3,
fun(Hook@1) ->
{Hook_id@2, Handle_event@1} = case Hook@1 of
{client, Hook_id@1, _, Handle_event} -> {
Hook_id@1,
Handle_event};
_assert_fail ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"sprocket/runtime"/utf8>>,
function => <<"handle_message"/utf8>>,
line => 194,
value => _assert_fail,
start => 5374,
'end' => 5428,
pattern_start => 5385,
pattern_end => 5421}
)
end,
Reply_dispatcher = fun(
Kind@3,
Payload@3
) ->
(erlang:element(
8,
erlang:element(2, State)
))(Hook_id@2, Kind@3, Payload@3)
end,
_pipe@4 = Handle_event@1,
gleam@option:map(
_pipe@4,
fun(Handle_event@2) ->
Handle_event@2(
Kind@2,
Payload@2,
Reply_dispatcher
)
end
)
end
)
end
)
end,
gleam@otp@actor:continue(State)
end
);
{update_hook_state, Hook_id@3, Update_fn} ->
Updated = begin
_pipe@5 = erlang:element(3, State),
gleam@option:map(
_pipe@5,
fun(Reconciled@2) ->
find_and_update_hook(
Reconciled@2,
Hook_id@3,
fun(Hook@2) -> case Hook@2 of
{state, Id, _} ->
case Id =:= Hook_id@3 of
true ->
Update_fn(Hook@2);
false ->
Hook@2
end;
_ ->
Hook@2
end end
)
end
)
end,
gleam@otp@actor:continue(
begin
_record = State,
{state,
erlang:element(2, _record),
Updated,
erlang:element(4, _record),
erlang:element(5, _record)}
end
);
{dispatch_client_hook_event, Hook_id@4, Kind@4, Payload@4} ->
_ = begin
_pipe@6 = gleam@list:find(
erlang:element(5, erlang:element(2, State)),
fun(H@5) ->
{client_hook_id, _, _, Client_hook_id} = H@5,
Client_hook_id =:= Hook_id@4
end
),
gleam@result:map(
_pipe@6,
fun(H@6) ->
{client_hook_id, Element_id@3, Hook_name@1, _} = H@6,
(erlang:element(5, State))(
{outbound_client_hook_event,
sprocket@internal@utils@unique:to_string(
Element_id@3
),
Hook_name@1,
Kind@4,
Payload@4}
)
end
)
end,
gleam@otp@actor:continue(State);
{reconcile_immediate, Reply_with@2} ->
Prev_reconciled = erlang:element(3, State),
El = erlang:element(2, erlang:element(2, State)),
{Ctx, Reconciled@3} = do_reconciliation(
erlang:element(2, State),
El,
Prev_reconciled
),
gleam@otp@actor:send(Reply_with@2, Reconciled@3),
gleam@otp@actor:continue(
begin
_record@1 = State,
{state,
Ctx,
{some, Reconciled@3},
erlang:element(4, _record@1),
erlang:element(5, _record@1)}
end
);
render_update ->
Prev_reconciled@1 = erlang:element(3, State),
Dispatch = erlang:element(5, State),
El@1 = erlang:element(2, erlang:element(2, State)),
{Ctx@1, Reconciled@4} = do_reconciliation(
erlang:element(2, State),
El@1,
Prev_reconciled@1
),
case Prev_reconciled@1 of
{some, Prev_reconciled@2} ->
Update = sprocket@internal@patch:create(
Prev_reconciled@2,
Reconciled@4
),
gleam@bool:guard(
Update =:= no_op,
nil,
fun() -> case Dispatch({patch_update, Update}) of
{ok, _} ->
nil;
{error, _} ->
sprocket@internal@logger:error(
<<"Failed to send update patch!"/utf8>>
),
nil
end end
);
none ->
case Dispatch({full_update, Reconciled@4}) of
{ok, _} ->
nil;
{error, _} ->
sprocket@internal@logger:error(
<<"Failed to send full reconciled update!"/utf8>>
),
nil
end
end,
gleam@otp@actor:continue(
begin
_record@2 = State,
{state,
Ctx@1,
{some, Reconciled@4},
erlang:element(4, _record@2),
erlang:element(5, _record@2)}
end
)
end.
-file("src/sprocket/runtime.gleam", 306).
?DOC(false).
-spec start(
sprocket@internal@context:element(),
fun((runtime_message()) -> {ok, nil} | {error, nil})
) -> {ok, gleam@erlang@process:subject(message())} |
{error, gleam@otp@actor:start_error()}.
start(El, Dispatch) ->
_pipe@3 = gleam@otp@actor:new_with_initialiser(
1000,
fun(Self) ->
Trigger_reconciliation = fun() ->
sprocket@internal@logger:debug(
<<"actor.send RenderUpdate"/utf8>>
),
gleam@otp@actor:send(Self, render_update)
end,
Update_hook = fun(Id, Updater) ->
sprocket@internal@logger:debug(
<<"actor.send UpdateHookState"/utf8>>
),
gleam@otp@actor:send(Self, {update_hook_state, Id, Updater})
end,
Cuid_channel@1 = case begin
_pipe = sprocket@internal@utils@cuid:start(),
gleam@result:map_error(
_pipe,
fun(Error) ->
sprocket@internal@logger:error(
<<"runtime.start: error starting cuid process"/utf8>>
),
Error
end
)
end of
{ok, Cuid_channel} -> Cuid_channel;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"sprocket/runtime"/utf8>>,
function => <<"start"/utf8>>,
line => 322,
value => _assert_fail,
start => 8921,
'end' => 9097,
pattern_start => 8932,
pattern_end => 8948})
end,
Dispatch_client_hook_event = fun(Id@1, Kind, Payload) ->
sprocket@internal@logger:debug(
<<"actor.send DispatchClientHookEvent"/utf8>>
),
gleam@otp@actor:send(
Self,
{dispatch_client_hook_event, Id@1, Kind, Payload}
)
end,
Model = {state,
sprocket@internal@context:new(
El,
Cuid_channel@1,
Dispatch_client_hook_event,
Trigger_reconciliation,
Update_hook
),
none,
Cuid_channel@1,
Dispatch},
_ = render_update(Self),
_pipe@1 = gleam@otp@actor:initialised(Model),
_pipe@2 = gleam@otp@actor:returning(_pipe@1, Self),
{ok, _pipe@2}
end
),
_pipe@4 = gleam@otp@actor:on_message(_pipe@3, fun handle_message/2),
_pipe@5 = gleam@otp@actor:start(_pipe@4),
_pipe@6 = gleam@result:map(
_pipe@5,
fun(Started) ->
Actor = erlang:element(3, Started),
sprocket@internal@logger:debug(
<<"runtime.start: runtime actor started"/utf8>>
),
Actor
end
),
gleam@result:map_error(
_pipe@6,
fun(Error@1) ->
sprocket@internal@logger:error(
<<"runtime.start: error starting runtime actor"/utf8>>
),
Error@1
end
).