Skip to content

Commit

Permalink
Use explicit request queue instead of process mailbox
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexey Nikitin committed Jan 7, 2019
1 parent e5fda93 commit fd212f9
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 21 deletions.
2 changes: 1 addition & 1 deletion doc/bookish_spork.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ stub_request_fun() = fun((<a href="bookish_spork_request.md#type-t">bookish_spor
### capture_request/0 ###

<pre><code>
capture_request() -&gt; <a href="bookish_spork_request.md#type-bookish_spork_request">bookish_spork_request:bookish_spork_request()</a>
capture_request() -&gt; {ok, Request::<a href="bookish_spork_request.md#type-t">bookish_spork_request:t()</a>} | {error, ErrorMessage::string()}
</code></pre>
<br />

Expand Down
21 changes: 20 additions & 1 deletion doc/bookish_spork_server.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ __Behaviours:__ [`gen_server`](gen_server.md).



### <a name="type-request">request()</a> ###


<pre><code>
request() = <a href="bookish_spork_request.md#type-t">bookish_spork_request:t()</a>
</code></pre>




### <a name="type-response">response()</a> ###


Expand All @@ -26,7 +36,7 @@ response() = <a href="bookish_spork_response.md#type-t">bookish_spork_response:t
## Function Index ##


<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#respond_with-1">respond_with/1</a></td><td></td></tr><tr><td valign="top"><a href="#start-1">start/1</a></td><td>starts server.</td></tr><tr><td valign="top"><a href="#stop-0">stop/0</a></td><td>stops server.</td></tr></table>
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#respond_with-1">respond_with/1</a></td><td></td></tr><tr><td valign="top"><a href="#retrieve_request-0">retrieve_request/0</a></td><td></td></tr><tr><td valign="top"><a href="#start-1">start/1</a></td><td>starts server.</td></tr><tr><td valign="top"><a href="#stop-0">stop/0</a></td><td>stops server.</td></tr></table>


<a name="functions"></a>
Expand All @@ -42,6 +52,15 @@ respond_with(Response::<a href="#type-response">response()</a>) -&gt; ok
</code></pre>
<br />

<a name="retrieve_request-0"></a>

### retrieve_request/0 ###

<pre><code>
retrieve_request() -&gt; {ok, Request::<a href="#type-request">request()</a>} | {error, ErrorMessage::string()}
</code></pre>
<br />

<a name="start-1"></a>

### start/1 ###
Expand Down
14 changes: 4 additions & 10 deletions src/bookish_spork.erl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
]).

-define(DEFAUT_PORT, 32002).
-define(RECEIVE_REQUEST_TIMEOUT_MILLIS, 1000).

-type http_status() :: non_neg_integer().
-type stub_request_fun() :: fun((bookish_spork_request:t()) -> bookish_spork_response:response()).
Expand Down Expand Up @@ -84,13 +83,8 @@ stub_request(Status, ContentOrHeaders) ->
stub_request(Status, Headers, Content) ->
bookish_spork_server:respond_with(bookish_spork_response:new({Status, Headers, Content})).

-spec capture_request() -> bookish_spork_request:bookish_spork_request().
-spec capture_request() ->
{ok, Request :: bookish_spork_request:t()} |
{error, ErrorMessage :: string()}.
capture_request() ->
receive
{bookish_spork, Request} ->
{ok, Request};
Unexpected ->
{unexpected, Unexpected}
after ?RECEIVE_REQUEST_TIMEOUT_MILLIS ->
timeout
end.
bookish_spork_server:retrieve_request().
36 changes: 28 additions & 8 deletions src/bookish_spork_server.erl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
-export([
start/1,
stop/0,
respond_with/1
respond_with/1,
retrieve_request/0
]).

-behaviour(gen_server).
Expand All @@ -19,9 +20,11 @@
-define(SERVER, ?MODULE).

-type response() :: bookish_spork_response:t() | bookish_spork:stub_request_fun().
-type request() :: bookish_spork_request:t().

-record(state, {
response_queue = queue:new() :: queue:queue({response(), pid()}),
response_queue = queue:new() :: queue:queue(response()),
request_queue = queue:new() :: queue:queue(request()),
acceptor :: pid(),
socket :: gen_tcp:socket()
}).
Expand All @@ -42,7 +45,16 @@ stop() ->
respond_with(Response) ->
gen_server:call(?SERVER, {respond_with, Response}).

-spec response() -> {Response :: response(), Receiver :: pid()}.
-spec retrieve_request() -> {ok, Request :: request()} | {error, ErrorMessage :: string()}.
retrieve_request() ->
gen_server:call(?SERVER, request).

-spec store_request(Request :: request()) -> ok.
%% @private
store_request(Request) ->
gen_server:call(?SERVER, {request, Request}).

-spec response() -> Response :: response().
%% @private
response() ->
gen_server:call(?SERVER, response).
Expand All @@ -65,12 +77,20 @@ init(Port) ->
State :: state()
) -> {reply, {ok, pid()}, state()}.
%% @private
handle_call({respond_with, Response}, {Receiver, _Ref}, #state{response_queue = Q1} = State) ->
Q2 = queue:in({Response, Receiver}, Q1),
{reply, ok, State#state{response_queue = Q2}};
handle_call({respond_with, Response}, _From, #state{response_queue = Q} = State) ->
{reply, ok, State#state{response_queue = queue:in(Response, Q)}};
handle_call({request, Request}, _From, #state{request_queue = Q} = State) ->
{reply, ok, State#state{request_queue = queue:in(Request, Q)}};
handle_call(response, _From, #state{response_queue = Q1} = State) ->
{{value, Val}, Q2} = queue:out(Q1),
{reply, Val, State#state{response_queue = Q2}};
handle_call(request, _From, #state{request_queue = Q1} = State) ->
case queue:out(Q1) of
{{value, Val}, Q2} ->
{reply, {ok, Val}, State#state{request_queue = Q2}};
{empty, _} ->
{reply, {error, "There were no requests"}, State}
end;
handle_call(_Request, _From, State) ->
{reply, {error, unknown_call}, State}.

Expand Down Expand Up @@ -103,8 +123,8 @@ accept(ListenSocket) ->
handle_connection(Socket) ->
case receive_request(Socket) of
{ok, Request} ->
{Response, Receiver} = response(),
Receiver ! {bookish_spork, Request},
store_request(Request),
Response = response(),
ok = reply(Socket, Response, Request),
complete_connection(Socket, Request);
socket_closed ->
Expand Down
2 changes: 1 addition & 1 deletion test/bookish_spork_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ customized_response_test(_Config) ->

failed_capture_test(_Config) ->
{ok, _Pid} = bookish_spork:start_server(),
?assertEqual(timeout, bookish_spork:capture_request(), "Got timeout when there is no stub"),
?assertMatch({error, _}, bookish_spork:capture_request(), "Got an error when there is no stub"),
ok = bookish_spork:stop_server().

stub_multiple_requests_test(_Config) ->
Expand Down

0 comments on commit fd212f9

Please sign in to comment.