anchor.diff:      cowboy_req:req(),
       EncodingFun :: fun((Data :: binary()) -> EncodedData :: binary()),
       ReadBlockSize :: non_neg_integer(),
  -    MaxReadBlocks :: non_neg_integer()
  +    MaxReadBlocks :: non_neg_integer(),
  +    SendRetryDelay :: non_neg_integer()
   ) ->
       ok | no_return().
  -stream_range(_, {From, To}, _, _, _, _) when From > To ->
  +stream_range(_, {From, To}, _, _, _, _, _) when From > To ->
       ok;
  -stream_range(FileHandle, {From, To}, Req, EncodingFun, ReadBlockSize, MaxReadBlocks) ->
  +stream_range(
  +    FileHandle, {From, To}, Req, EncodingFun,
  +    ReadBlockSize, MaxReadBlocks, SendRetryDelay
  +) ->
       ToRead = min(To - From + 1, ReadBlockSize - From rem ReadBlockSize),
       {ok, NewFileHandle, Data} = ?check(lfm:read(FileHandle, From, ToRead)),
   
  
positive.code:         0 ->
              ok;
          DataSize ->
              send_data(EncodingFun(Data), Req, MaxReadBlocks),
              stream_range(
                  NewFileHandle, {From + DataSize, To}, Req,
                  EncodingFun, ReadBlockSize, MaxReadBlocks
              )
      end.
  
  
negative.code: %% read into memory.
  %% @end
  %%--------------------------------------------------------------------
  -spec send_data(
      Data :: binary(),
      cowboy_req:req(),
      MaxReadBlocks :: non_neg_integer(),
      RetryDelay :: non_neg_integer()
  ) ->
      NextRetryDelay :: non_neg_integer().
  send_data(Data, #{pid := ConnPid} = Req, MaxReadBlocks, RetryDelay) ->
      {message_queue_len, MsgQueueLen} = process_info(ConnPid, message_queue_len),
  
      case MsgQueueLen < MaxReadBlocks of
          true ->
              cowboy_req:stream_body(Data, nofin, Req),
              min(RetryDelay div 2, ?MIN_SEND_RETRY_DELAY);
          false ->
              timer:sleep(RetryDelay),
              send_data(Data, Req, MaxReadBlocks, min(2 * RetryDelay, ?MAX_SEND_RETRY_DELAY))
      end.
  