use of org.zalando.nakadi.exceptions.InvalidCursorException in project nakadi by zalando.
the class KafkaTopicRepositoryTest method invalidateInvalidCursors.
@Test
@SuppressWarnings("ArraysAsListWithZeroOrOneArgument")
public void invalidateInvalidCursors() throws NakadiException {
final Cursor outOfBoundOffset = cursor("0", "38");
try {
kafkaTopicRepository.createEventConsumer(KAFKA_CLIENT_ID, asTopicPosition(MY_TOPIC, asList(outOfBoundOffset)));
} catch (final InvalidCursorException e) {
assertThat(e.getError(), equalTo(CursorError.UNAVAILABLE));
}
final Cursor nonExistingPartition = cursor("99", "100");
try {
kafkaTopicRepository.createEventConsumer(KAFKA_CLIENT_ID, asTopicPosition(MY_TOPIC, asList(nonExistingPartition)));
} catch (final InvalidCursorException e) {
assertThat(e.getError(), equalTo(CursorError.PARTITION_NOT_FOUND));
}
final Cursor wrongOffset = cursor("0", "blah");
try {
kafkaTopicRepository.createEventConsumer(KAFKA_CLIENT_ID, asTopicPosition(MY_TOPIC, asList(wrongOffset)));
} catch (final InvalidCursorException e) {
assertThat(e.getError(), equalTo(CursorError.INVALID_FORMAT));
}
}
use of org.zalando.nakadi.exceptions.InvalidCursorException in project nakadi by zalando.
the class EventStreamControllerTest method whenInvalidCursorsThenPreconditionFailed.
@Test
public void whenInvalidCursorsThenPreconditionFailed() throws Exception {
final NakadiCursor cursor = NakadiCursor.of(timeline, "0", "000000000000000000");
when(eventTypeRepository.findByName(TEST_EVENT_TYPE_NAME)).thenReturn(EVENT_TYPE);
when(timelineService.createEventConsumer(eq(KAFKA_CLIENT_ID), any())).thenThrow(new InvalidCursorException(CursorError.UNAVAILABLE, cursor));
final StreamingResponseBody responseBody = createStreamingResponseBody(1, 0, 0, 0, 0, "[{\"partition\":\"0\",\"offset\":\"00000000000000000\"}]");
final Problem expectedProblem = Problem.valueOf(PRECONDITION_FAILED, "offset 000000000000000000 for partition 0 is unavailable");
assertThat(responseToString(responseBody), TestUtils.JSON_TEST_HELPER.matchesObject(expectedProblem));
}
use of org.zalando.nakadi.exceptions.InvalidCursorException in project nakadi by zalando.
the class CursorsService method validateStreamId.
private void validateStreamId(final List<NakadiCursor> cursors, final String streamId, final ZkSubscriptionClient subscriptionClient) throws ServiceUnavailableException, InvalidCursorException, InvalidStreamIdException {
if (!uuidGenerator.isUUID(streamId)) {
throw new InvalidStreamIdException(String.format("Stream id has to be valid UUID, but `%s was provided", streamId), streamId);
}
if (!subscriptionClient.isActiveSession(streamId)) {
throw new InvalidStreamIdException("Session with stream id " + streamId + " not found", streamId);
}
final Map<EventTypePartition, String> partitionSessions = Stream.of(subscriptionClient.getTopology().getPartitions()).collect(Collectors.toMap(Partition::getKey, Partition::getSession));
for (final NakadiCursor cursor : cursors) {
final EventTypePartition etPartition = cursor.getEventTypePartition();
final String partitionSession = partitionSessions.get(etPartition);
if (partitionSession == null) {
throw new InvalidCursorException(CursorError.PARTITION_NOT_FOUND, cursor);
}
if (!streamId.equals(partitionSession)) {
throw new InvalidStreamIdException("Cursor " + cursor + " cannot be committed with stream id " + streamId, streamId);
}
}
}
use of org.zalando.nakadi.exceptions.InvalidCursorException 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;
}
use of org.zalando.nakadi.exceptions.InvalidCursorException in project nakadi by zalando.
the class SubscriptionValidationService method validateInitialCursors.
private void validateInitialCursors(final SubscriptionBase subscription, final List<EventTypePartition> allPartitions) throws WrongInitialCursorsException, RepositoryProblemException {
final boolean cursorsMissing = allPartitions.stream().anyMatch(p -> !subscription.getInitialCursors().stream().anyMatch(p::ownsCursor));
if (cursorsMissing) {
throw new WrongInitialCursorsException("initial_cursors should contain cursors for all partitions of subscription");
}
final boolean hasCursorForWrongPartition = subscription.getInitialCursors().stream().anyMatch(c -> !allPartitions.contains(new EventTypePartition(c.getEventType(), c.getPartition())));
if (hasCursorForWrongPartition) {
throw new WrongInitialCursorsException("initial_cursors should contain cursors only for partitions of this subscription");
}
if (subscription.getInitialCursors().size() > allPartitions.size()) {
throw new WrongInitialCursorsException("there should be no more than 1 cursor for each partition in initial_cursors");
}
try {
for (final SubscriptionCursorWithoutToken cursor : subscription.getInitialCursors()) {
final NakadiCursor nakadiCursor = cursorConverter.convert(cursor);
if (nakadiCursor.getTimeline().isDeleted()) {
throw new InvalidCursorException(UNAVAILABLE, nakadiCursor);
}
timelineService.getTopicRepository(nakadiCursor.getTimeline()).validateReadCursors(Collections.singletonList(nakadiCursor));
}
} catch (final InvalidCursorException ex) {
throw new WrongInitialCursorsException(ex.getMessage(), ex);
} catch (final NakadiException ex) {
throw new RepositoryProblemException("Topic repository problem occurred when validating cursors", ex);
}
}
Aggregations