docs: protected <T extends HttpResponseAware> T updateRateLimit(Supplier<T> httpResponseAwareSupplier) {
      if (rateLimitReset != null) {
        long waitMillis = rateLimitReset * 1000 - System.currentTimeMillis();
        if (rateLimitRemaining <= 0 && waitMillis >= 0) {
          throw new ExchangeException(
              "The request is not executed due to rate limit, please wait for "
                  + (waitMillis / 1000)
                  + " seconds, limit:"
                  + rateLimit
                  + ", reset: "
                  + new Date(rateLimitReset * 1000));
        } else {
          rateLimitRemaining--;
        }
      }
      HttpResponseAware responseAware = null;
      boolean rateLimitsUpdated = false;
      try {
        T result = httpResponseAwareSupplier.get();
        responseAware = result;
        return result;
      } catch (BitmexException e) {
        if (e.getHttpStatusCode() == 429) {
          // we are warned !
          try {
            Integer retryAfter = Integer.valueOf(e.getResponseHeaders().get("Retry-After").get(0));
            rateLimitRemaining = 0;
            rateLimitReset = System.currentTimeMillis() / 1000 + retryAfter;
            rateLimitsUpdated = true;
          } catch (Throwable ignored) {
          }
        } else if (e.getHttpStatusCode() == 403) {
          // we are banned now !
          rateLimitRemaining = 0;
          rateLimitReset = System.currentTimeMillis() / 1000 + 5; // lets be quiet for 5 sec
        }
        responseAware = e;
        throw handleError(e);
      } catch (Exception e) {
        throw handleError(e);
      } finally {
        if (responseAware != null && !rateLimitsUpdated) {
          Map<String, List<String>> responseHeaders = responseAware.getResponseHeaders();
          rateLimit = Integer.valueOf(responseHeaders.get("X-RateLimit-Limit").get(0));
          rateLimitRemaining = Integer.valueOf(responseHeaders.get("X-RateLimit-Remaining").get(0));
          rateLimitReset = Long.valueOf(responseHeaders.get("X-RateLimit-Reset").get(0));
          rateLimitsUpdated = true;
        }
        if (rateLimitsUpdated) {
          RateLimitUpdateListener rateLimitUpdateListener = exchange.getRateLimitUpdateListener();
          if (rateLimitUpdateListener != null) {
            rateLimitUpdateListener.rateLimitUpdate(rateLimit, rateLimitRemaining, rateLimitReset);
          }
        }
      }
    }