use of org.zalando.nakadi.domain.Timeline in project nakadi by zalando.
the class SubscriptionValidationServiceTest method mockCursorWithTimeline.
private static NakadiCursor mockCursorWithTimeline() {
final Timeline timeline = mock(Timeline.class);
when(timeline.isDeleted()).thenReturn(false);
final NakadiCursor cursor = mock(NakadiCursor.class);
when(cursor.getTimeline()).thenReturn(timeline);
return cursor;
}
use of org.zalando.nakadi.domain.Timeline in project nakadi by zalando.
the class CursorOperationsService method moveBack.
private NakadiCursor moveBack(final ShiftedNakadiCursor cursor) {
NakadiCursor currentCursor = cursor.getNakadiCursor();
long toMoveBack = -cursor.getShift();
while (toMoveBack > 0) {
final long totalBefore = numberOfEventsBeforeCursor(currentCursor);
if (totalBefore < toMoveBack) {
// +1 is because end is inclusive
toMoveBack -= totalBefore + 1;
// begin event that is not within limits)
if (toMoveBack == 0) {
toMoveBack += totalBefore + 1;
break;
}
final Timeline prevTimeline = getTimeline(currentCursor.getEventType(), currentCursor.getTimeline().getOrder() - 1);
// When moving back latest position is always defined
currentCursor = prevTimeline.getLatestPosition().toNakadiCursor(prevTimeline, currentCursor.getPartition());
} else {
break;
}
}
if (toMoveBack != 0) {
currentCursor = currentCursor.shiftWithinTimeline(-toMoveBack);
}
return currentCursor;
}
use of org.zalando.nakadi.domain.Timeline in project nakadi by zalando.
the class EventTypeService method delete.
public void delete(final String eventTypeName) throws EventTypeDeletionException, AccessDeniedException, NoEventTypeException, ConflictException, ServiceTemporarilyUnavailableException, DbWriteOperationsBlockedException {
if (featureToggleService.isFeatureEnabled(FeatureToggleService.Feature.DISABLE_DB_WRITE_OPERATIONS)) {
throw new DbWriteOperationsBlockedException("Cannot delete event type: write operations on DB " + "are blocked by feature flag.");
}
Closeable deletionCloser = null;
final EventType eventType;
Multimap<TopicRepository, String> topicsToDelete = null;
try {
deletionCloser = timelineSync.workWithEventType(eventTypeName, nakadiSettings.getTimelineWaitTimeoutMs());
final Optional<EventType> eventTypeOpt = eventTypeRepository.findByNameO(eventTypeName);
if (!eventTypeOpt.isPresent()) {
throw new NoEventTypeException("EventType \"" + eventTypeName + "\" does not exist.");
}
eventType = eventTypeOpt.get();
authorizationValidator.authorizeEventTypeAdmin(eventType);
final List<Subscription> subscriptions = subscriptionRepository.listSubscriptions(ImmutableSet.of(eventTypeName), Optional.empty(), 0, 1);
if (!subscriptions.isEmpty()) {
throw new ConflictException("Can't remove event type " + eventTypeName + ", as it has subscriptions");
}
topicsToDelete = transactionTemplate.execute(action -> deleteEventType(eventTypeName));
} catch (final InterruptedException e) {
Thread.currentThread().interrupt();
LOG.error("Failed to wait for timeline switch", e);
throw new EventTypeUnavailableException("Event type " + eventTypeName + " is currently in maintenance, please repeat request");
} catch (final TimeoutException e) {
LOG.error("Failed to wait for timeline switch", e);
throw new EventTypeUnavailableException("Event type " + eventTypeName + " is currently in maintenance, please repeat request");
} catch (final NakadiException e) {
LOG.error("Error deleting event type " + eventTypeName, e);
throw new EventTypeDeletionException("Failed to delete event type " + eventTypeName);
} finally {
try {
if (deletionCloser != null) {
deletionCloser.close();
}
} catch (final IOException e) {
LOG.error("Exception occurred when releasing usage of event-type", e);
}
}
if (topicsToDelete != null) {
for (final TopicRepository topicRepository : topicsToDelete.keySet()) {
for (final String topic : topicsToDelete.get(topicRepository)) {
try {
topicRepository.deleteTopic(topic);
} catch (TopicDeletionException e) {
// If a timeline was marked as deleted, then the topic does not exist, and we should proceed.
LOG.info("Could not delete topic " + topic, e);
}
}
}
}
nakadiKpiPublisher.publish(etLogEventType, () -> new JSONObject().put("event_type", eventTypeName).put("status", "deleted").put("category", eventType.getCategory()).put("authz", identifyAuthzState(eventType)).put("compatibility_mode", eventType.getCompatibilityMode()));
}
use of org.zalando.nakadi.domain.Timeline in project nakadi by zalando.
the class TimelineCleanupJob method deleteTimelinesLocked.
private void deleteTimelinesLocked() {
final List<Timeline> expired = timelineDbRepository.getExpiredTimelines();
for (int i = 0; i < expired.size(); ++i) {
if (i != 0 && deletionDelayMs > 0) {
try {
Thread.sleep(deletionDelayMs);
} catch (InterruptedException e) {
LOG.warn("Timeline deletion thread was interrupted", e);
Thread.currentThread().interrupt();
return;
}
}
final Timeline timeline = expired.get(i);
deleteTimelineTopic(timeline);
markTimelineDeleted(timeline);
}
}
use of org.zalando.nakadi.domain.Timeline 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