dispcount icon indicating copy to clipboard operation
dispcount copied to clipboard

Add dispcount:transaction/2 for running funs in watcher context

Open Vagabond opened this issue 5 years ago • 2 comments

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.

Vagabond avatar Mar 24 '20 20:03 Vagabond

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.

Vagabond avatar Mar 24 '20 20:03 Vagabond

Sounds workable; might make sense to identify which request returns which results with a Ref, allowing people to parallelize calls.

ferd avatar Apr 01 '20 00:04 ferd