use of org.zalando.nakadi.domain.NakadiCursor in project nakadi by zalando.
the class CursorConverterImplTest method testBeginConvertedVersionZero.
@Test
public void testBeginConvertedVersionZero() throws Exception {
final String eventType = "test-et";
final String partition = "2";
final Storage storage = new Storage("", Storage.Type.KAFKA);
final Timeline timeline = mock(Timeline.class);
when(timeline.getStorage()).thenReturn(storage);
final EventTypeCache eventTypeCache = mock(EventTypeCache.class);
final TopicRepository topicRepository = mock(TopicRepository.class);
final TimelineService timelineService = mock(TimelineService.class);
final PartitionStatistics stats = mock(PartitionStatistics.class);
when(timelineService.getActiveTimelinesOrdered(eq(eventType))).thenReturn(Collections.singletonList(timeline));
when(timelineService.getTopicRepository(eq(timeline))).thenReturn(topicRepository);
when(topicRepository.loadPartitionStatistics(eq(timeline), eq(partition))).thenReturn(Optional.of(stats));
final NakadiCursor beforeFirstCursor = NakadiCursor.of(timeline, partition, "000001");
when(stats.getBeforeFirst()).thenReturn(beforeFirstCursor);
final CursorConverter converter = new CursorConverterImpl(eventTypeCache, timelineService);
final NakadiCursor nakadiCursor = converter.convert(eventType, new Cursor(partition, "BEGIN"));
Assert.assertEquals(timeline, nakadiCursor.getTimeline());
Assert.assertEquals(partition, nakadiCursor.getPartition());
Assert.assertEquals("000001", nakadiCursor.getOffset());
}
use of org.zalando.nakadi.domain.NakadiCursor in project nakadi by zalando.
the class StreamingState method reconfigureKafkaConsumer.
private void reconfigureKafkaConsumer(final boolean forceSeek) {
if (eventConsumer == null) {
throw new IllegalStateException("kafkaConsumer should not be null when calling reconfigureKafkaConsumer method");
}
final Set<EventTypePartition> newAssignment = offsets.keySet().stream().filter(o -> !this.releasingPartitions.containsKey(o)).collect(Collectors.toSet());
if (forceSeek) {
// removing all the current assignments for real consumer.
try {
eventConsumer.reassign(Collections.emptyList());
} catch (final NakadiException | InvalidCursorException ex) {
throw new NakadiRuntimeException(ex);
}
}
final Set<EventTypePartition> currentAssignment = eventConsumer.getAssignment();
getLog().info("Changing kafka assignment from {} to {}", Arrays.deepToString(currentAssignment.toArray()), Arrays.deepToString(newAssignment.toArray()));
if (!currentAssignment.equals(newAssignment)) {
try {
final Map<EventTypePartition, NakadiCursor> beforeFirst = getBeforeFirstCursors(newAssignment);
final List<NakadiCursor> cursors = newAssignment.stream().map(pk -> {
final NakadiCursor beforeFirstAvailable = beforeFirst.get(pk);
// Checks that current cursor is still available in storage
offsets.get(pk).ensureDataAvailable(beforeFirstAvailable);
return offsets.get(pk).getSentOffset();
}).collect(Collectors.toList());
eventConsumer.reassign(cursors);
} catch (NakadiException | InvalidCursorException ex) {
throw new NakadiRuntimeException(ex);
}
}
}
use of org.zalando.nakadi.domain.NakadiCursor in project nakadi by zalando.
the class ClosingState method reactOnOffset.
private void reactOnOffset(final EventTypePartition key) {
if (!listeners.containsKey(key)) {
return;
}
final NakadiCursor newCursor;
try {
newCursor = getContext().getCursorConverter().convert(key.getEventType(), listeners.get(key).getData());
} catch (Exception ex) {
throw new NakadiRuntimeException(ex);
}
if (uncommittedOffsets.containsKey(key) && getComparator().compare(uncommittedOffsets.get(key), newCursor) <= 0) {
freePartitions(Collections.singletonList(key));
}
tryCompleteState();
}
use of org.zalando.nakadi.domain.NakadiCursor 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.domain.NakadiCursor in project nakadi by zalando.
the class CursorOperationsService method moveForward.
private NakadiCursor moveForward(final ShiftedNakadiCursor cursor) {
NakadiCursor currentCursor = cursor.getNakadiCursor();
long stillToAdd = cursor.getShift();
while (currentCursor.getTimeline().getLatestPosition() != null) {
final NakadiCursor timelineLastPosition = currentCursor.getTimeline().getLatestPosition().toNakadiCursor(currentCursor.getTimeline(), currentCursor.getPartition());
final long distance = calculateDistance(currentCursor, timelineLastPosition);
if (stillToAdd > distance) {
stillToAdd -= distance;
final Timeline nextTimeline = getTimeline(currentCursor.getEventType(), currentCursor.getTimeline().getOrder() + 1);
currentCursor = NakadiCursor.of(nextTimeline, currentCursor.getPartition(), StaticStorageWorkerFactory.get(nextTimeline).getBeforeFirstOffset());
} else {
break;
}
}
if (stillToAdd > 0) {
return currentCursor.shiftWithinTimeline(stillToAdd);
}
return currentCursor;
}
Aggregations