@Builder private BatchedPermitsRequester(String resourceId, String requestorIdentifier, long targetMillisBetweenRequests, RequestSender requestSender, MetricContext metricContext) { Preconditions.checkArgument(!Strings.isNullOrEmpty(resourceId), "Must provide a resource id."); Preconditions.checkArgument(!Strings.isNullOrEmpty(requestorIdentifier), "Must provide a requestor identifier."); this.permitBatchContainer = new PermitBatchContainer(); this.lock = new ReentrantLock(); this.newPermitsAvailable = this.lock.newCondition(); /** Ensures there is only one in-flight request at a time. */ this.requestSemaphore = new Semaphore(1); /** Number of not-yet-satisfied permits. */ this.permitsOutstanding = new SynchronizedAverager(); this.targetMillisBetweenRequests = targetMillisBetweenRequests > 0 ? targetMillisBetweenRequests : DEFAULT_TARGET_MILLIS_BETWEEN_REQUESTS; this.requestSender = requestSender; this.retryStatus = new RetryStatus(); this.basePermitRequest = new PermitRequest(); this.basePermitRequest.setResource(resourceId); this.basePermitRequest.setRequestorIdentifier(requestorIdentifier); this.restRequestTimer = metricContext == null ? null : metricContext.timer(REST_REQUEST_TIMER); this.restRequestHistogram = metricContext == null ? null : metricContext.histogram(REST_REQUEST_PERMITS_HISTOGRAM); this.callbackCounter = new AtomicLong(); }