use of org.zalando.nakadi.domain.CursorError.PARTITION_NOT_FOUND in project nakadi by zalando.
the class VersionZeroConverter method convertBatched.
public List<NakadiCursor> convertBatched(final List<SubscriptionCursorWithoutToken> cursors) throws InvalidCursorException, InternalNakadiException, NoSuchEventTypeException, ServiceUnavailableException {
final NakadiCursor[] result = new NakadiCursor[cursors.size()];
for (int idx = 0; idx < cursors.size(); ++idx) {
final SubscriptionCursorWithoutToken cursor = cursors.get(idx);
if (Cursor.BEFORE_OLDEST_OFFSET.equalsIgnoreCase(cursor.getOffset())) {
// Preform begin checks afterwards to optimize calls
continue;
}
if (!NUMBERS_ONLY_PATTERN.matcher(cursor.getOffset()).matches()) {
throw new InvalidCursorException(CursorError.INVALID_OFFSET, cursor);
}
}
// now it is time for massive convert.
final LinkedHashMap<SubscriptionCursorWithoutToken, NakadiCursor> beginsToConvert = new LinkedHashMap<>();
final Map<SubscriptionCursorWithoutToken, Timeline> cursorTimelines = new HashMap<>();
final Map<TopicRepository, List<SubscriptionCursorWithoutToken>> repos = new HashMap<>();
for (int i = 0; i < result.length; ++i) {
if (null == result[i]) {
// cursor requires database hit
final SubscriptionCursorWithoutToken cursor = cursors.get(i);
final Timeline timeline = timelineService.getActiveTimelinesOrdered(cursor.getEventType()).get(0);
final TopicRepository topicRepo = timelineService.getTopicRepository(timeline);
beginsToConvert.put(cursor, null);
cursorTimelines.put(cursor, timeline);
repos.computeIfAbsent(topicRepo, k -> new ArrayList<>()).add(cursor);
}
}
for (final Map.Entry<TopicRepository, List<SubscriptionCursorWithoutToken>> entry : repos.entrySet()) {
final List<Optional<PartitionStatistics>> stats = entry.getKey().loadPartitionStatistics(entry.getValue().stream().map(scwt -> new TopicRepository.TimelinePartition(cursorTimelines.get(scwt), scwt.getPartition())).collect(Collectors.toList()));
for (int idx = 0; idx < entry.getValue().size(); ++idx) {
// Reinsert doesn't change the order
beginsToConvert.put(entry.getValue().get(idx), stats.get(idx).orElseThrow(() -> new InvalidCursorException(PARTITION_NOT_FOUND)).getBeforeFirst());
}
}
final Iterator<NakadiCursor> missingBegins = beginsToConvert.values().iterator();
return Stream.of(result).map(it -> null == it ? missingBegins.next() : it).collect(Collectors.toList());
}
use of org.zalando.nakadi.domain.CursorError.PARTITION_NOT_FOUND in project nakadi by zalando.
the class KafkaTopicRepository method convertToKafkaCursors.
private Map<NakadiCursor, KafkaCursor> convertToKafkaCursors(final List<NakadiCursor> cursors) throws ServiceUnavailableException, InvalidCursorException {
final List<Timeline> timelines = cursors.stream().map(NakadiCursor::getTimeline).distinct().collect(toList());
final List<PartitionStatistics> statistics = loadTopicStatistics(timelines);
final Map<NakadiCursor, KafkaCursor> result = new HashMap<>();
for (final NakadiCursor position : cursors) {
validateCursorForNulls(position);
final Optional<PartitionStatistics> partition = statistics.stream().filter(t -> Objects.equals(t.getPartition(), position.getPartition())).filter(t -> Objects.equals(t.getTimeline().getTopic(), position.getTopic())).findAny();
if (!partition.isPresent()) {
throw new InvalidCursorException(PARTITION_NOT_FOUND, position);
}
final KafkaCursor toCheck = position.asKafkaCursor();
// Checking oldest position
final KafkaCursor oldestCursor = KafkaCursor.fromNakadiCursor(partition.get().getBeforeFirst());
if (toCheck.compareTo(oldestCursor) < 0) {
throw new InvalidCursorException(UNAVAILABLE, position);
}
// checking newest position
final KafkaCursor newestPosition = KafkaCursor.fromNakadiCursor(partition.get().getLast());
if (toCheck.compareTo(newestPosition) > 0) {
throw new InvalidCursorException(UNAVAILABLE, position);
} else {
result.put(position, toCheck);
}
}
return result;
}
Aggregations