11-module (shackle_server ).
22-include (" shackle_internal.hrl" ).
33
4- -compile (inline ).
5- -compile ({inline_size , 512 }).
6-
74-export ([
85 start_link /2
96]).
2623 pool_name :: shackle_pool :name (),
2724 port :: shackle :inet_port (),
2825 protocol :: shackle :protocol (),
29- queue :: shackle :table (),
26+ queue = #{} :: #{shackle :external_request_id () =>
27+ {shackle :cast (), reference ()}},
3028 reconnect_state :: undefined | reconnect_state (),
3129 socket :: undefined | shackle :socket (),
3230 socket_options :: shackle :socket_options (),
@@ -86,7 +84,6 @@ init(Name, Parent, Opts) ->
8684 pool_name = PoolName ,
8785 port = Port ,
8886 protocol = Protocol ,
89- queue = shackle_queue :table_name (PoolName ),
9087 reconnect_state = ReconnectState ,
9188 socket_options = SocketOptions
9289 }, undefined }}.
@@ -104,7 +101,6 @@ handle_msg({Request, #cast {
104101 timeout = Timeout
105102 } = Cast }, {# state {
106103 client = Client ,
107- id = Id ,
108104 pool_name = PoolName ,
109105 protocol = Protocol ,
110106 queue = Queue ,
@@ -118,14 +114,15 @@ handle_msg({Request, #cast {
118114 shackle_telemetry :send (Client , iolist_size (Data )),
119115 case ExtRequestId of
120116 undefined ->
121- reply (ok , Cast , State );
117+ reply (ok , Cast , State ),
118+ {ok , {State , ClientState2 }};
122119 _ ->
123120 Msg = {timeout , ExtRequestId },
124121 TimerRef = erlang :send_after (Timeout , self (), Msg ),
125- shackle_queue : add ( Queue , Id , ExtRequestId , Cast ,
126- TimerRef )
127- end ,
128- { ok , { State , ClientState2 }} ;
122+ Queue2 = maps : put ( ExtRequestId , { Cast , TimerRef } ,
123+ Queue ),
124+ { ok , { State # state { queue = Queue2 }, ClientState2 }}
125+ end ;
129126 {error , Reason } ->
130127 ? WARN (PoolName , " send error: ~p " , [Reason ]),
131128 Protocol :close (Socket ),
@@ -139,6 +136,24 @@ handle_msg({Request, #cast {
139136 reply ({error , client_crash }, Cast , State ),
140137 {ok , {State , ClientState }}
141138 end ;
139+ handle_msg ({'$socket' , Socket , select , _Handle }, {# state {
140+ socket = Socket
141+ } = State , ClientState }) ->
142+
143+ case shackle_socket :recv (Socket ) of
144+ {ok , Data } ->
145+ handle_msg_data (Socket , Data , State , ClientState );
146+ wait ->
147+ {ok , {State , ClientState }};
148+ {error , closed } ->
149+ handle_msg_close (Socket , State , ClientState );
150+ {error , Reason } ->
151+ handle_msg_error (Socket , Reason , State , ClientState )
152+ end ;
153+ handle_msg ({'$socket' , _Socket , select , _Handle }, {State , ClientState }) ->
154+ {ok , {State , ClientState }};
155+ handle_msg ({'$socket' , Socket , abort , _Info }, {State , ClientState }) ->
156+ handle_msg_close (Socket , State , ClientState );
142157handle_msg ({ssl , Socket , Data }, {State , ClientState }) ->
143158 handle_msg_data (Socket , Data , State , ClientState );
144159handle_msg ({ssl_closed , Socket }, {State , ClientState }) ->
@@ -187,7 +202,6 @@ handle_msg(?MSG_CONNECT, {#state {
187202 end ;
188203handle_msg ({timeout , ExtRequestId }, {# state {
189204 client = Client ,
190- id = Id ,
191205 pool_name = PoolName ,
192206 protocol = Protocol ,
193207 queue = Queue ,
@@ -199,8 +213,8 @@ handle_msg({timeout, ExtRequestId}, {#state {
199213 try Client :handle_timeout (ExtRequestId , ClientState ) of
200214 {ok , Reply , ClientState2 } ->
201215 shackle_telemetry :handle_timeout (Client ),
202- process_responses ([Reply ], State ),
203- {ok , {State , ClientState2 }};
216+ State2 = process_responses ([Reply ], State ),
217+ {ok , {State2 , ClientState2 }};
204218 {error , Reason , ClientState2 } ->
205219 ? WARN (PoolName , " handle_timeout error: ~p " , [Reason ]),
206220 Protocol :close (Socket ),
@@ -213,14 +227,14 @@ handle_msg({timeout, ExtRequestId}, {#state {
213227 close (State , ClientState )
214228 end ;
215229 false ->
216- case shackle_queue : remove ( Queue , Id , ExtRequestId ) of
217- {ok , Cast , _TimerRef } ->
230+ case maps : take ( ExtRequestId , Queue ) of
231+ {{ Cast , _TimerRef }, Queue2 } ->
218232 shackle_telemetry :timeout (Client ),
219- reply ({error , timeout }, Cast , State );
220- { error , not_found } ->
221- ok
222- end ,
223- { ok , { State , ClientState }}
233+ reply ({error , timeout }, Cast , State ),
234+ { ok , { State # state { queue = Queue2 }, ClientState }};
235+ error ->
236+ { ok , { State , ClientState }}
237+ end
224238 end ;
225239handle_msg (Msg , {# state {
226240 pool_name = PoolName
@@ -303,8 +317,8 @@ client_setup(Client, PoolName, Protocol, Socket, ClientState) ->
303317
304318close (# state {id = Id } = State , ClientState ) ->
305319 shackle_status :disable (Id ),
306- reply_all ({error , socket_closed }, State ),
307- reconnect (State , ClientState ).
320+ State2 = reply_all ({error , socket_closed }, State ),
321+ reconnect (State2 , ClientState ).
308322
309323connect (Protocol , Address , Port , SocketOptions , PoolName ) ->
310324 case inet :getaddrs (Address , inet ) of
@@ -342,8 +356,8 @@ handle_msg_data(Socket, Data, #state {
342356 shackle_telemetry :recv (Client , size (Data )),
343357 try Client :handle_data (Data , ClientState ) of
344358 {ok , Replies , ClientState2 } ->
345- process_responses (Replies , State ),
346- {ok , {State , ClientState2 }};
359+ State2 = process_responses (Replies , State ),
360+ {ok , {State2 , ClientState2 }};
347361 {error , Reason , ClientState2 } ->
348362 ? WARN (PoolName , " handle_data error: ~p " , [Reason ]),
349363 Protocol :close (Socket ),
@@ -370,27 +384,26 @@ handle_msg_error(Socket, Reason, #state {
370384handle_msg_error (_Socket , _Reason , State , ClientState ) ->
371385 {ok , {State , ClientState }}.
372386
373- process_responses ([], _State ) ->
374- ok ;
387+ process_responses ([], State ) ->
388+ State ;
375389process_responses ([{ExtRequestId , Reply } | T ], # state {
376390 client = Client ,
377- id = Id ,
378391 queue = Queue
379392 } = State ) ->
380393
381394 shackle_telemetry :replies (Client ),
382- case shackle_queue : remove ( Queue , Id , ExtRequestId ) of
383- {ok , # cast {timestamp = Timestamp } = Cast , TimerRef } ->
395+ case maps : take ( ExtRequestId , Queue ) of
396+ {{ # cast {timestamp = Timestamp } = Cast , TimerRef }, Queue2 } ->
384397 shackle_telemetry :found (Client ),
385398 Diff = erlang :monotonic_time (microsecond ) - Timestamp ,
386399 shackle_telemetry :reply (Client , Diff ),
387400 erlang :cancel_timer (TimerRef ),
388- reply (Reply , Cast , State );
389- {error , not_found } ->
401+ reply (Reply , Cast , State ),
402+ process_responses (T , State # state {queue = Queue2 });
403+ error ->
390404 shackle_telemetry :not_found (Client ),
391- ok
392- end ,
393- process_responses (T , State ).
405+ process_responses (T , State )
406+ end .
394407
395408reconnect (State , undefined ) ->
396409 reconnect_timer (State , undefined );
@@ -459,22 +472,18 @@ reply(_Reply, #cast {pid = undefined}, #state {
459472
460473 shackle_backlog :decrement (Backlog , Id ),
461474 ok ;
462- reply (Reply , # cast {pid = Pid } = Cast , # state {
475+ reply (Reply , # cast {pid = Pid , request_id = RequestId } , # state {
463476 backlog = Backlog ,
464477 id = Id
465478 }) ->
466479
467480 shackle_backlog :decrement (Backlog , Id ),
468- Pid ! {Cast , Reply },
481+ Pid ! {shackle_reply , RequestId , Reply },
469482 ok .
470483
471- reply_all (Reply , # state {
472- id = Id ,
473- queue = Queue
474- } = State ) ->
475-
476- Requests = shackle_queue :clear (Queue , Id ),
477- reply_all (Reply , Requests , State ).
484+ reply_all (Reply , # state {queue = Queue } = State ) ->
485+ reply_all (Reply , maps :values (Queue ), State ),
486+ State # state {queue = #{}}.
478487
479488reply_all (_Reply , [], _State ) ->
480489 ok ;
0 commit comments