dispcount
dispcount copied to clipboard
Add dispcount:transaction/2 for running funs in watcher context
To avoid unnecessary calls and waiting for responses allow for a fun to be passed as a transaction that can be run by the watcher. As soon as the fun completes, the watcher is marked as free again without intervention by the calling process. This should improve throughput for use cases where the caller having direct access to the resource is not necessary.
This still needs tests, but I have it working in the field.
Here's how I'm using it, with epgsql's async mode:
prepared_query(Pool, Name, Params) ->
Ref = make_ref(),
Fun = fun(From, {Stmts, Conn}) ->
Statement = maps:get(Name, Stmts),
#statement{types = Types} = Statement,
TypedParameters = lists:zip(Types, Params),
%% construct the same kind of cast the epgsqla:prepared_statement does, but redirect
%% the output to the elli process directly
gen_server:cast(Conn, {{cast, From, Ref}, epgsql_cmd_prepared_query, {Statement, TypedParameters}})
end,
case dispcount:transaction(Pool, Fun) of
ok ->
receive
{_Conn, Ref, Res} ->
Res
after
500 ->
throw(?RESPONSE_503)
end;
{error, busy} ->
throw(?RESPONSE_503)
end.
Sounds workable; might make sense to identify which request returns which results with a Ref, allowing people to parallelize calls.