use of org.springframework.cloud.gcp.pubsub.support.AcknowledgeablePubsubMessage in project spring-cloud-gcp by spring-cloud.
the class PubSubSubscriberTemplateTests method testPull_AndManualNack.
@Test
public void testPull_AndManualNack() throws InterruptedException, ExecutionException, TimeoutException {
List<AcknowledgeablePubsubMessage> result = this.pubSubSubscriberTemplate.pull("sub2", 1, true);
assertThat(result.size()).isEqualTo(1);
assertThat(result.get(0).getPubsubMessage()).isSameAs(this.pubsubMessage);
assertThat(result.get(0).getProjectSubscriptionName().getProject()).isEqualTo("testProject");
assertThat(result.get(0).getProjectSubscriptionName().getSubscription()).isEqualTo("sub2");
AcknowledgeablePubsubMessage acknowledgeablePubsubMessage = result.get(0);
assertThat(acknowledgeablePubsubMessage.getAckId()).isNotNull();
TestListenableFutureCallback testListenableFutureCallback = new TestListenableFutureCallback();
ListenableFuture<Void> listenableFuture = this.pubSubSubscriberTemplate.nack(result);
assertThat(listenableFuture).isNotNull();
listenableFuture.addCallback(testListenableFutureCallback);
listenableFuture.get(10L, TimeUnit.SECONDS);
assertThat(listenableFuture.isDone()).isTrue();
assertThat(testListenableFutureCallback.getThrowable()).isNull();
}
use of org.springframework.cloud.gcp.pubsub.support.AcknowledgeablePubsubMessage in project spring-cloud-gcp by spring-cloud.
the class PubSubTemplateIntegrationTests method testPullAndAck.
@Test
public void testPullAndAck() {
this.contextRunner.run((context) -> {
PubSubAdmin pubSubAdmin = context.getBean(PubSubAdmin.class);
String topicName = "peel-the-paint" + UUID.randomUUID();
String subscriptionName = "i-lost-my-head" + UUID.randomUUID();
pubSubAdmin.createTopic(topicName);
pubSubAdmin.createSubscription(subscriptionName, topicName, 10);
PubSubTemplate pubSubTemplate = context.getBean(PubSubTemplate.class);
List<Future<String>> futures = new ArrayList<>();
futures.add(pubSubTemplate.publish(topicName, "message1"));
futures.add(pubSubTemplate.publish(topicName, "message2"));
futures.add(pubSubTemplate.publish(topicName, "message3"));
futures.parallelStream().forEach((f) -> {
try {
f.get(5, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException ex) {
LOGGER.error(ex);
Thread.currentThread().interrupt();
}
});
List<AcknowledgeablePubsubMessage> ackableMessages = new ArrayList<>();
Set<String> messagesSet = new HashSet<>();
for (int i = 0; i < 5 && messagesSet.size() < 3; i++) {
List<AcknowledgeablePubsubMessage> newMessages = pubSubTemplate.pull(subscriptionName, 4, false);
ackableMessages.addAll(newMessages);
messagesSet.addAll(newMessages.stream().map((message) -> message.getPubsubMessage().getData().toStringUtf8()).collect(Collectors.toList()));
}
assertThat(messagesSet.size()).as("check that we received all the messages").isEqualTo(3);
ackableMessages.forEach((message) -> {
try {
if (message.getPubsubMessage().getData().toStringUtf8().equals("message1")) {
// sync call
message.ack().get();
} else {
// sync call
message.nack().get();
}
} catch (InterruptedException | ExecutionException ex) {
LOGGER.error(ex);
Thread.currentThread().interrupt();
}
});
Thread.sleep(11_000);
// pull the 2 nacked messages with retries for up to 10s
int messagesCount = 0;
int tries = 100;
while (messagesCount < 2 && tries > 0) {
Thread.sleep(100);
ackableMessages = pubSubTemplate.pull(subscriptionName, 4, true);
ackableMessages.forEach((m) -> m.ack());
messagesCount += ackableMessages.size();
tries--;
}
assertThat(messagesCount).as("check that we get both nacked messages back").isEqualTo(2);
pubSubAdmin.deleteSubscription(subscriptionName);
pubSubAdmin.deleteTopic(topicName);
});
}
use of org.springframework.cloud.gcp.pubsub.support.AcknowledgeablePubsubMessage in project spring-cloud-gcp by spring-cloud.
the class WebController method pull.
@GetMapping("/pull")
public RedirectView pull(@RequestParam("subscription1") String subscriptionName) {
Collection<AcknowledgeablePubsubMessage> messages = this.pubSubTemplate.pull(subscriptionName, 10, true);
if (messages.isEmpty()) {
return buildStatusView("No messages available for retrieval.");
}
RedirectView returnView;
try {
ListenableFuture<Void> ackFuture = this.pubSubTemplate.ack(messages);
ackFuture.get();
returnView = buildStatusView(String.format("Pulled and acked %s message(s)", messages.size()));
} catch (Exception ex) {
LOGGER.warn("Acking failed.", ex);
returnView = buildStatusView("Acking failed");
}
return returnView;
}
use of org.springframework.cloud.gcp.pubsub.support.AcknowledgeablePubsubMessage in project spring-cloud-gcp by spring-cloud.
the class WebController method multipull.
@GetMapping("/multipull")
public RedirectView multipull(@RequestParam("subscription1") String subscriptionName1, @RequestParam("subscription2") String subscriptionName2) {
Set<AcknowledgeablePubsubMessage> mixedSubscriptionMessages = new HashSet<>();
mixedSubscriptionMessages.addAll(this.pubSubTemplate.pull(subscriptionName1, 1000, true));
mixedSubscriptionMessages.addAll(this.pubSubTemplate.pull(subscriptionName2, 1000, true));
if (mixedSubscriptionMessages.isEmpty()) {
return buildStatusView("No messages available for retrieval.");
}
RedirectView returnView;
try {
ListenableFuture<Void> ackFuture = this.pubSubTemplate.ack(mixedSubscriptionMessages);
ackFuture.get();
returnView = buildStatusView(String.format("Pulled and acked %s message(s)", mixedSubscriptionMessages.size()));
} catch (Exception ex) {
LOGGER.warn("Acking failed.", ex);
returnView = buildStatusView("Acking failed");
}
return returnView;
}
use of org.springframework.cloud.gcp.pubsub.support.AcknowledgeablePubsubMessage in project spring-cloud-gcp by spring-cloud.
the class PubSubReactiveFactoryTests method setUpMessages.
/**
* Replays provided messages.
* If a synthetic message "stop" is encountered, immediately returns previously collected messages.
* If a synthetic message "timeout" is encountered, throws an {@link DeadlineExceededException}.
* If a synthetic message "throw" is encountered, throws an {@link RuntimeException}.
* Fails the calling test if there are not enough messages to fulfill demand from cumulative calls to {@code pull()}.
* @param messages messages to replay
*/
private void setUpMessages(String... messages) {
List<String> msgList = new ArrayList<>(Arrays.asList(messages));
when(subscriberOperations.pullAsync(eq("sub1"), any(Integer.class), any(Boolean.class))).then(invocationOnMock -> {
List<AcknowledgeablePubsubMessage> result = new ArrayList<>();
for (int i = 0; i < (Integer) invocationOnMock.getArgument(1); i++) {
if (msgList.isEmpty()) {
fail("Ran out of provided messages.");
}
String nextPayload = msgList.remove(0);
switch(nextPayload) {
case "stop":
return AsyncResult.forValue(result);
case "timeout":
if (!result.isEmpty()) {
fail("Bad setup -- 'throw' should be the first event in batch");
}
return AsyncResult.forExecutionException(new DeadlineExceededException("this is a noop", null, GrpcStatusCode.of(Status.Code.DEADLINE_EXCEEDED), true));
case "throw":
return AsyncResult.forExecutionException(new RuntimeException("expected exception during pull of messages"));
}
AcknowledgeablePubsubMessage msg = mock(AcknowledgeablePubsubMessage.class);
PubsubMessage pubsubMessage = PubsubMessage.newBuilder().setData(ByteString.copyFrom((nextPayload).getBytes())).build();
when(msg.getPubsubMessage()).thenReturn(pubsubMessage);
result.add(msg);
}
return AsyncResult.forValue(result);
});
}
Aggregations