Current section
Files
Jump to
Current section
Files
src/aion@internal@pump.erl
-module(aion@internal@pump).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/aion/internal/pump.gleam").
-export([run/1]).
-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(
" The workflow-side query pump loop around suspending awaits.\n"
"\n"
" The engine answers workflow queries at yield points (AT-007 C20): when a\n"
" query is pending for the workflow, a suspending await returns the\n"
" sentinel `Error(\"aion_query:\" <> json)` instead of resolving. `run`\n"
" recognises the sentinel, services the query through\n"
" `aion_flow_query_pump` (handler lookup, try/catch, reply), and re-enters\n"
" the same await, which re-resolves identically — pump iterations are\n"
" invisible to history and to replay. Every other result passes through\n"
" untouched.\n"
).
-file("src/aion/internal/pump.gleam", 21).
?DOC(
" Run a suspending await thunk, servicing any pending queries the engine\n"
" surfaces as `aion_query:` sentinels before the await's own resolution.\n"
"\n"
" The loop is tail-recursive: each serviced query is answered exactly once,\n"
" then the await is re-entered until it resolves with a non-sentinel\n"
" result. A query handler raise never crashes the workflow — the Erlang\n"
" pump converts it into a `reply_query_error` and the loop continues.\n"
).
-spec run(fun(() -> {ok, binary()} | {error, binary()})) -> {ok, binary()} |
{error, binary()}.
run(Do) ->
case Do() of
{error, <<"aion_query:"/utf8, Sentinel_payload/binary>>} ->
aion_flow_query_pump:service(Sentinel_payload),
run(Do);
Outcome ->
Outcome
end.