@Override public Boolean call() throws Exception { return container.getPermits(permits); } });
@VisibleForTesting public void clearAllStoredPermits() { this.bachedPermitsContainer.clearAllStoredPermits(); } }
/** * Clear all stored permits. */ @VisibleForTesting public void clearAllStoredPermits() { this.getPermitBatchContainer().purgeAll(); } }
@Builder private RestliServiceBasedLimiter(String resourceLimited, String serviceIdentifier, MetricContext metricContext, RequestSender requestSender) { Preconditions.checkNotNull(requestSender, "Request sender cannot be null."); this.bachedPermitsContainer = BatchedPermitsRequester.builder() .resourceId(resourceLimited).requestorIdentifier(serviceIdentifier).requestSender(requestSender).build(); this.metricContext = Optional.fromNullable(metricContext); if (this.metricContext.isPresent()) { this.permitsRequestedMeter = Optional.of(this.metricContext.get().meter(PERMITS_REQUESTED_METER_NAME)); this.permitsGrantedMeter = Optional.of(this.metricContext.get().meter(PERMITS_GRANTED_METER_NAME)); } else { this.permitsRequestedMeter = Optional.absent(); this.permitsGrantedMeter = Optional.absent(); } }
maybeSendNewPermitRequest(); if (this.callbackCounter.get() == callbackCounterSnap) {
long permits = computeNextPermitRequest(); if (permits <= 0) { this.requestSemaphore.release();
@Test public void testForwardingOfRequests() throws Exception { Queue<RequestAndCallback> queue = Queues.newArrayDeque(); BatchedPermitsRequester container = BatchedPermitsRequester.builder().resourceId("resource") .requestorIdentifier("requestor").requestSender(new TestRequestSender(queue, false)).build(); try (ParallelRequester requester = new ParallelRequester(container)) { Future<Boolean> future = requester.request(10); await(new QueueSize(queue, 1), 1000); Assert.assertEquals(queue.size(), 1); satisfyRequestBuilder().requestAndCallback(queue.poll()).satisfy(); future.get(1, TimeUnit.SECONDS); Assert.assertTrue(future.isDone()); Assert.assertTrue(future.get()); } }
@Test public void testNonRetriableFail() throws Exception { Queue<RequestAndCallback> queue = Queues.newArrayDeque(); BatchedPermitsRequester container = BatchedPermitsRequester.builder().resourceId("resource") .requestorIdentifier("requestor").requestSender(new TestRequestSender(queue, false)).build(); try (ParallelRequester requester = new ParallelRequester(container)) { Future<Boolean> future = requester.request(10); // container should only try request once await(new QueueSize(queue, 1), 1000); Assert.assertFalse(future.isDone()); failRequestBuilder().requestAndCallback(queue.poll()).errorStatus(HttpStatus.S_422_UNPROCESSABLE_ENTITY).fail(); Assert.assertFalse(future.get()); Assert.assertEquals(queue.size(), 0); } }
@Override public Closeable acquirePermits(long permits) throws InterruptedException { Instrumented.markMeter(this.permitsRequestedMeter, permits); boolean permitsGranted = this.bachedPermitsContainer.getPermits(permits); Instrumented.markMeter(this.permitsGrantedMeter, permits); return permitsGranted ? NoopCloseable.INSTANCE : null; }
/** * @return the number of permits acquired from the server and not yet used. */ @VisibleForTesting public long getUnusedPermits() { return this.bachedPermitsContainer.getPermitBatchContainer().getTotalAvailablePermits(); }
Queue<RequestAndCallback> queue = Queues.newArrayDeque(); BatchedPermitsRequester container = BatchedPermitsRequester.builder().resourceId("resource") .requestorIdentifier("requestor").requestSender(new TestRequestSender(queue, false)).build(); try (ParallelRequester requester = new ParallelRequester(container)) {
@Test public void testRetriableFail() throws Exception { Queue<RequestAndCallback> queue = Queues.newArrayDeque(); BatchedPermitsRequester container = BatchedPermitsRequester.builder().resourceId("resource") .requestorIdentifier("requestor").requestSender(new TestRequestSender(queue, false)).build(); try (ParallelRequester requester = new ParallelRequester(container)) { Future<Boolean> future = requester.request(10); for (int i = 0; i < BatchedPermitsRequester.MAX_RETRIES; i++) { // container will fail 5 times await(new QueueSize(queue, 1), 1000); Assert.assertFalse(future.isDone()); failRequestBuilder().requestAndCallback(queue.poll()).fail(); } // should return a failure Assert.assertFalse(future.get()); // should not make any more request Assert.assertEquals(queue.size(), 0); } }