@Override public void onResponse(StreamingPullResponse response) { channelReconnectBackoffMillis.set(INITIAL_CHANNEL_RECONNECT_BACKOFF.toMillis()); messageDispatcher.processReceivedMessages( response.getReceivedMessagesList(), new Runnable() { @Override public void run() { // Only request more if we're not shutdown. // If errorFuture is done, the stream has either failed or hung up, // and we don't need to request. if (isAlive() && !errorFuture.isDone()) { lock.lock(); try { thisController.request(1); } catch (Exception e) { logger.log(Level.WARNING, "cannot request more messages", e); } finally { lock.unlock(); } } } }); }
@Test public void testAck() throws Exception { dispatcher.processReceivedMessages(Collections.singletonList(TEST_MESSAGE), NOOP_RUNNABLE); consumers.take().ack(); dispatcher.processOutstandingAckOperations(); assertThat(sentAcks).contains(TEST_MESSAGE.getAckId()); }
@Test public void testReceipt() throws Exception { dispatcher.processReceivedMessages(Collections.singletonList(TEST_MESSAGE), NOOP_RUNNABLE); dispatcher.processOutstandingAckOperations(); assertThat(sentModAcks) .contains(ModAckItem.of(TEST_MESSAGE.getAckId(), Subscriber.MIN_ACK_DEADLINE_SECONDS)); }
@Test public void testNack() throws Exception { dispatcher.processReceivedMessages(Collections.singletonList(TEST_MESSAGE), NOOP_RUNNABLE); consumers.take().nack(); dispatcher.processOutstandingAckOperations(); assertThat(sentModAcks).contains(ModAckItem.of(TEST_MESSAGE.getAckId(), 0)); }
@Test public void testDeadlineAdjustment() throws Exception { assertThat(dispatcher.computeDeadlineSeconds()).isEqualTo(10); dispatcher.processReceivedMessages(Collections.singletonList(TEST_MESSAGE), NOOP_RUNNABLE); clock.advance(42, TimeUnit.SECONDS); consumers.take().ack(); assertThat(dispatcher.computeDeadlineSeconds()).isEqualTo(42); } }
@Test public void testExtension() throws Exception { dispatcher.processReceivedMessages(Collections.singletonList(TEST_MESSAGE), NOOP_RUNNABLE); dispatcher.extendDeadlines(); assertThat(sentModAcks) .contains(ModAckItem.of(TEST_MESSAGE.getAckId(), Subscriber.MIN_ACK_DEADLINE_SECONDS)); sentModAcks.clear(); consumers.take().ack(); dispatcher.extendDeadlines(); assertThat(sentModAcks).isEmpty(); }
@Test public void testExtension_Close() throws Exception { dispatcher.processReceivedMessages(Collections.singletonList(TEST_MESSAGE), NOOP_RUNNABLE); dispatcher.extendDeadlines(); assertThat(sentModAcks) .contains(ModAckItem.of(TEST_MESSAGE.getAckId(), Subscriber.MIN_ACK_DEADLINE_SECONDS)); sentModAcks.clear(); // Default total expiration is an hour (60*60 seconds). We normally would extend by 10s. // However, only extend by 5s here, since there's only 5s left before total expiration. clock.advance(60 * 60 - 5, TimeUnit.SECONDS); dispatcher.extendDeadlines(); assertThat(sentModAcks).contains(ModAckItem.of(TEST_MESSAGE.getAckId(), 5)); }
@Test public void testExtension_GiveUp() throws Exception { dispatcher.processReceivedMessages(Collections.singletonList(TEST_MESSAGE), NOOP_RUNNABLE); dispatcher.extendDeadlines(); assertThat(sentModAcks) .contains(ModAckItem.of(TEST_MESSAGE.getAckId(), Subscriber.MIN_ACK_DEADLINE_SECONDS)); sentModAcks.clear(); // If we run extendDeadlines after totalExpiration, we shouldn't send anything. // In particular, don't send negative modacks. clock.advance(1, TimeUnit.DAYS); dispatcher.extendDeadlines(); assertThat(sentModAcks).isEmpty(); // We should be able to reserve another item in the flow controller and not block shutdown flowController.reserve(1, 0); dispatcher.stop(); }