use of co.cask.cdap.messaging.MessageFetcher in project cdap by caskdata.
the class MessagingNotificationService method subscribe.
@Override
public <N> Cancellable subscribe(NotificationFeedId feed, NotificationHandler<N> handler, Executor executor) throws NotificationFeedNotFoundException, NotificationFeedException {
Cancellable subscribeCancellable = super.subscribe(feed, handler, executor);
// If already has a thread fetching, just return the cancellable.
if (!needFetch.compareAndSet(false, true)) {
return subscribeCancellable;
}
// Start fetching
subscribeExecutor.execute(new Runnable() {
private final long startTime = System.currentTimeMillis();
private final RetryStrategy scheduleStrategy = RetryStrategies.exponentialDelay(100, 3000, TimeUnit.MILLISECONDS);
private byte[] messageId;
private int emptyFetchCount;
@Override
public void run() {
try {
MessageFetcher fetcher = messagingService.prepareFetch(notificationTopic);
if (messageId == null) {
fetcher.setStartTime(startTime);
} else {
fetcher.setStartMessage(messageId, false);
}
emptyFetchCount++;
try (CloseableIterator<RawMessage> iterator = fetcher.fetch()) {
while (iterator.hasNext()) {
emptyFetchCount = 0;
RawMessage rawMessage = iterator.next();
NotificationMessage message = GSON.fromJson(new String(rawMessage.getPayload(), StandardCharsets.UTF_8), NotificationMessage.class);
try {
LOG.trace("Decoded notification: {}", message);
notificationReceived(message.getFeedId(), message.getNotificationJson());
} catch (Throwable t) {
LOG.warn("Error while processing notification {} with handler {}", message, t);
}
messageId = rawMessage.getId();
}
}
} catch (Exception e) {
LOG.error("Failed to get notification", e);
}
// Back-off if it was empty fetch.
if (emptyFetchCount > 0) {
// Schedule the next fetch. Exponential strategy doesn't use the time component,
// so doesn't matter what we passed in
subscribeExecutor.schedule(this, scheduleStrategy.nextRetry(emptyFetchCount, startTime), TimeUnit.MILLISECONDS);
} else {
subscribeExecutor.execute(this);
}
}
});
return subscribeCancellable;
}
use of co.cask.cdap.messaging.MessageFetcher in project cdap by caskdata.
the class FetchHandler method fetchMessages.
/**
* Creates a {@link CloseableIterator} of {@link RawMessage} based on the given fetch request.
*/
private CloseableIterator<RawMessage> fetchMessages(GenericRecord fetchRequest, TopicId topicId) throws IOException, TopicNotFoundException {
MessageFetcher fetcher = messagingService.prepareFetch(topicId);
Object startFrom = fetchRequest.get("startFrom");
if (startFrom != null) {
if (startFrom instanceof ByteBuffer) {
// start message id is specified
fetcher.setStartMessage(Bytes.toBytes((ByteBuffer) startFrom), (Boolean) fetchRequest.get("inclusive"));
} else if (startFrom instanceof Long) {
// start by timestamp is specified
fetcher.setStartTime((Long) startFrom);
} else {
// This shouldn't happen as it's guaranteed by the schema
LOG.warn("Ignore unrecognized type for startFrom. Type={}, Value={}", startFrom.getClass(), startFrom);
}
}
Integer limit = (Integer) fetchRequest.get("limit");
if (limit != null) {
fetcher.setLimit(limit);
}
ByteBuffer encodedTx = (ByteBuffer) fetchRequest.get("transaction");
if (encodedTx != null) {
fetcher.setTransaction(TRANSACTION_CODEC.decode(ByteBuffers.getByteArray(encodedTx)));
}
return fetcher.fetch();
}
Aggregations