diff --git a/src/eimap.erl b/src/eimap.erl --- a/src/eimap.erl +++ b/src/eimap.erl @@ -146,6 +146,21 @@ disconnected(Command, State) when is_record(Command, command) -> { next_state, disconnected, enque_command(Command, State) }. + +%Throttle if the target process is getting overloaded. +%This allows the socket buffers to fill up eventually, +%so regular congestion control can kick in. +throttle(Receiver, Limit) -> + {_, MessageQueueLength} = process_info(Receiver, message_queue_len), + if + MessageQueueLength > Limit -> + SleepDuration = trunc(MessageQueueLength / 2), + lager:debug("Throttling for ~p with queue length ~p", [SleepDuration, MessageQueueLength]), + timer:sleep(SleepDuration), + throttle(Receiver, Limit); + true -> false + end. + passthrough(flush_passthrough_buffer, #state{ passthrough_send_buffer = Buffer } = State) -> %lager:info("Passing through ~p", [Buffer]), passthrough({ passthrough, Buffer }, State#state{ passthrough_send_buffer = <<>> }); @@ -159,6 +174,8 @@ { next_state, passthrough, State }; passthrough({ data, Data }, #state{ passthrough_recv = Receiver } = State) -> %lager:info("Passing back ~p", [Data]), + + throttle(Receiver, 100), Receiver ! { imap_server_response, Data }, { next_state, passthrough, State }; passthrough(Command, State) when is_record(Command, command) ->