use of org.zalando.nakadi.exceptions.runtime.InvalidCursorOperation in project nakadi by zalando.
the class CursorOperationsServiceTest method shiftCursorToExpiredTimeline.
@Test
public void shiftCursorToExpiredTimeline() throws Exception {
final Timeline initialTimeline = mockTimeline(1, 5L);
final Timeline finalTimeline = mockTimeline(1);
when(timelineService.getActiveTimelinesOrdered(any())).thenReturn(Lists.newArrayList(initialTimeline, finalTimeline));
final ShiftedNakadiCursor shiftedCursor = new ShiftedNakadiCursor(finalTimeline, "0", "000000000000000003", -15L);
try {
service.unshiftCursor(shiftedCursor);
fail();
} catch (final InvalidCursorOperation e) {
assertThat(e.getReason(), equalTo(TIMELINE_NOT_FOUND));
} catch (final Exception e) {
fail();
}
}
use of org.zalando.nakadi.exceptions.runtime.InvalidCursorOperation in project nakadi by zalando.
the class CursorOperationsService method calculateDistance.
public long calculateDistance(final NakadiCursor initialCursor, final NakadiCursor finalCursor) throws InvalidCursorOperation {
// Validate query
if (!initialCursor.getPartition().equals(finalCursor.getPartition())) {
throw new InvalidCursorOperation(CURSORS_WITH_DIFFERENT_PARTITION);
}
long result = numberOfEventsBeforeCursor(finalCursor) - numberOfEventsBeforeCursor(initialCursor);
final int initialOrder = initialCursor.getTimeline().getOrder();
final int finalOrder = finalCursor.getTimeline().getOrder();
int startOrder = Math.min(initialOrder, finalOrder);
if (startOrder == Timeline.STARTING_ORDER) {
startOrder += 1;
}
for (int order = startOrder; order < Math.max(initialOrder, finalOrder); ++order) {
final Timeline timeline = getTimeline(initialCursor.getEventType(), order);
final long eventsTotal = getStorageWorker(timeline).totalEventsInPartition(timeline, initialCursor.getPartition());
result += (finalOrder > initialOrder) ? eventsTotal : -eventsTotal;
}
return result;
}
use of org.zalando.nakadi.exceptions.runtime.InvalidCursorOperation in project nakadi by zalando.
the class CursorOperationsService method cursorsLag.
public List<NakadiCursorLag> cursorsLag(final String eventTypeName, final List<NakadiCursor> cursors) throws InvalidCursorOperation {
try {
final List<Timeline> timelines = timelineService.getActiveTimelinesOrdered(eventTypeName);
// Next 2 calls could be optimized to 1 storage call, instead of possible 2 calls.
// But it is simpler not to do anything, cause timelines are not switched every day and almost all the time
// (except retention time after switch) there will be only 1 active timeline, and this option is covered.
final List<PartitionStatistics> oldestStats = getStatsForTimeline(timelines.get(0));
final List<PartitionStatistics> newestStats = timelines.size() == 1 ? oldestStats : getStatsForTimeline(timelines.get(timelines.size() - 1));
return cursors.stream().map(c -> {
final PartitionStatistics oldestStat = oldestStats.stream().filter(item -> item.getPartition().equalsIgnoreCase(c.getPartition())).findAny().orElseThrow(() -> new InvalidCursorOperation(PARTITION_NOT_FOUND));
NakadiCursor newestPosition = newestStats.stream().filter(item -> item.getPartition().equalsIgnoreCase(c.getPartition())).map(PartitionEndStatistics::getLast).findAny().orElseThrow(() -> new InvalidCursorOperation(PARTITION_NOT_FOUND));
// it
while (numberOfEventsBeforeCursor(newestPosition) == -1) {
final int prevOrder = newestPosition.getTimeline().getOrder() - 1;
final Timeline prevTimeline = timelines.stream().filter(t -> t.getOrder() == prevOrder).findAny().orElse(null);
if (null == prevTimeline) {
break;
}
// We moved back, so timeline definitely have latest position set
newestPosition = prevTimeline.getLatestPosition().toNakadiCursor(prevTimeline, newestPosition.getPartition());
}
// calls (in case of kafka)
return new NakadiCursorLag(oldestStat.getFirst(), newestPosition, calculateDistance(c, newestPosition));
}).collect(Collectors.toList());
} catch (final NakadiException e) {
throw new MyNakadiRuntimeException1("error", e);
}
}
use of org.zalando.nakadi.exceptions.runtime.InvalidCursorOperation in project nakadi by zalando.
the class SubscriptionService method loadStats.
private List<SubscriptionEventTypeStats> loadStats(final Collection<EventType> eventTypes, final Optional<ZkSubscriptionNode> subscriptionNode, final ZkSubscriptionClient client, final List<PartitionEndStatistics> stats) throws ServiceTemporarilyUnavailableException, InconsistentStateException {
final List<SubscriptionEventTypeStats> result = new ArrayList<>(eventTypes.size());
final Collection<NakadiCursor> committedPositions = subscriptionNode.map(node -> loadCommittedPositions(node.getPartitions(), client)).orElse(Collections.emptyList());
for (final EventType eventType : eventTypes) {
final List<SubscriptionEventTypeStats.Partition> resultPartitions = new ArrayList<>(stats.size());
for (final PartitionEndStatistics stat : stats) {
final NakadiCursor lastPosition = stat.getLast();
if (!lastPosition.getEventType().equals(eventType.getName())) {
continue;
}
final Long distance = committedPositions.stream().filter(pos -> pos.getEventTypePartition().equals(lastPosition.getEventTypePartition())).findAny().map(committed -> {
try {
return cursorOperationsService.calculateDistance(committed, lastPosition);
} catch (final InvalidCursorOperation ex) {
throw new InconsistentStateException("Unexpected exception while calculating distance", ex);
}
}).orElse(null);
final Partition.State state = subscriptionNode.map(node -> node.guessState(stat.getTimeline().getEventType(), stat.getPartition())).orElse(Partition.State.UNASSIGNED);
final String streamId = subscriptionNode.map(node -> node.guessStream(stat.getTimeline().getEventType(), stat.getPartition())).orElse("");
final SubscriptionEventTypeStats.Partition.AssignmentType assignmentType = subscriptionNode.map(node -> node.getPartitionAssignmentType(stat.getTimeline().getEventType(), stat.getPartition())).orElse(null);
resultPartitions.add(new SubscriptionEventTypeStats.Partition(lastPosition.getPartition(), state.getDescription(), distance, streamId, assignmentType));
}
resultPartitions.sort(Comparator.comparing(SubscriptionEventTypeStats.Partition::getPartition));
result.add(new SubscriptionEventTypeStats(eventType.getName(), resultPartitions));
}
return result;
}
Aggregations