Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,10 @@ public synchronized ConsumerRecords<K, V> poll(final Duration timeout) {
if (!subscriptions.isPaused(entry.getKey())) {
final List<ConsumerRecord<K, V>> recs = entry.getValue();
for (final ConsumerRecord<K, V> rec : recs) {
if (beginningOffsets.get(entry.getKey()) != null && beginningOffsets.get(entry.getKey()) > subscriptions.position(entry.getKey())) {
throw new OffsetOutOfRangeException(Collections.singletonMap(entry.getKey(), subscriptions.position(entry.getKey())));
}

if (assignment().contains(entry.getKey()) && rec.offset() >= subscriptions.position(entry.getKey())) {
results.computeIfAbsent(entry.getKey(), partition -> new ArrayList<>()).add(rec);
subscriptions.position(entry.getKey(), rec.offset() + 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ public Collection<TopicPartition> restore(final RestoringTasks active) {
needsInitializing.remove(partition);
needsRestoring.remove(partition);

final StateRestorer restorer = stateRestorers.get(partition);
restorer.setCheckpointOffset(StateRestorer.NO_CHECKPOINT);
task.reinitializeStateStoresForPartitions(recoverableException.partitions());
}
restoreConsumer.seekToBeginning(partitions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,42 @@ public Set<TopicPartition> partitions() {
assertThat(callback.restored.size(), equalTo(messages));
}

@Test
public void shouldRecoverFromOffsetOutOfRangeExceptionAndRestoreFromStart() {
final int messages = 10;
final int startOffset = 5;
final long expiredCheckpoint = 1L;
assignPartition(messages, topicPartition);
consumer.updateBeginningOffsets(Collections.singletonMap(topicPartition, (long) startOffset));
consumer.updateEndOffsets(Collections.singletonMap(topicPartition, (long) (messages + startOffset)));

addRecords(messages, topicPartition, startOffset);
consumer.assign(Collections.<TopicPartition>emptyList());

final StateRestorer stateRestorer = new StateRestorer(
topicPartition,
restoreListener,
expiredCheckpoint,
Long.MAX_VALUE,
true,
"storeName");
Comment thread
linyli001 marked this conversation as resolved.
changelogReader.register(stateRestorer);

EasyMock.expect(active.restoringTaskFor(topicPartition)).andStubReturn(task);
EasyMock.replay(active, task);

// first restore call "fails" since OffsetOutOfRangeException but we should not die with an exception
assertEquals(0, changelogReader.restore(active).size());
//the starting offset for stateRestorer is set to NO_CHECKPOINT
assertThat(stateRestorer.checkpoint(), equalTo(-1L));

//restore the active task again
changelogReader.register(stateRestorer);
//the restored task should return completed partition without Exception.
assertEquals(1, changelogReader.restore(active).size());
//the restored size should be equal to message length.
assertThat(callback.restored.size(), equalTo(messages));
}

@Test
public void shouldRestoreMessagesFromCheckpoint() {
Expand Down