Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8dc0f50
remove commit from handleCorruption and handle TaskCorrupted in handl…
ableegoldman Mar 23, 2021
549a5f7
fixin up the tests
ableegoldman Mar 26, 2021
a843f11
skip only corrupted tasks when checkpointing in handleRevocation
ableegoldman Mar 26, 2021
dbec22d
checkstyle
ableegoldman Mar 26, 2021
4ce51e9
comments
ableegoldman Mar 26, 2021
7282884
clean up logic
ableegoldman Mar 26, 2021
5950b39
simplify even further
ableegoldman Mar 26, 2021
d6f8c0b
handle corrupted tasks
ableegoldman Mar 26, 2021
1a579a4
use own catch block
ableegoldman Mar 26, 2021
4d4f41c
add flag to closeAndRevive to conditionally mark changelogs as corru…
ableegoldman Mar 27, 2021
dc91e75
cleanup
ableegoldman Mar 27, 2021
1446ec2
fix test I messed with before
ableegoldman Mar 27, 2021
9c8730a
add unit test
ableegoldman Mar 27, 2021
723520b
backtrack on handleCorrupted, tick the task timer and add another test
ableegoldman Mar 27, 2021
e5cca19
Revert "backtrack on handleCorrupted, tick the task timer and add ano…
ableegoldman Mar 28, 2021
4a9ffff
add second unit test
ableegoldman Mar 28, 2021
669367f
Merge branch 'trunk' of https://github.com/apache/kafka into 12523-im…
ableegoldman Mar 28, 2021
4d23c99
cleanup in handleRevocation
ableegoldman Mar 28, 2021
0d21ff4
javadocs for commit
ableegoldman Mar 28, 2021
ecb7e7c
clear timeout in revive and refactor commit
ableegoldman Mar 28, 2021
9ea3256
update/remove comment
ableegoldman Mar 28, 2021
f6361c0
need to clear commit statuses during close
ableegoldman Mar 28, 2021
4aed51d
clear status in all kinds of close
ableegoldman Mar 28, 2021
9db590b
add timed out tasks to dirty tasks in handleRevocation
ableegoldman Mar 28, 2021
4c78a79
add StreamTaskTest
ableegoldman Mar 28, 2021
55c076b
add KAFKA-12569 jira number to TODOs
ableegoldman Mar 28, 2021
6fcdd56
add unit tests for eos
ableegoldman Mar 29, 2021
fa4cde5
fix flaky test due to strict mock
ableegoldman Mar 29, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,23 @@ void handleCorruption(final Set<TaskId> corruptedTasks) {
// since TaskMigrated can be thrown and the resulting handleLostAll will only clean up active tasks
closeAndRevive(corruptedStandbyTasks);

commit(tasks()
Comment thread
ableegoldman marked this conversation as resolved.
.values()
.stream()
.filter(t -> t.state() == Task.State.RUNNING || t.state() == Task.State.RESTORING)
.filter(t -> !corruptedTasks.contains(t.id()))
.collect(Collectors.toSet())
);
// We need to commit before closing the corrupted active tasks since this will force the ongoing txn to abort
try {
commit(tasks()
.values()
.stream()
.filter(t -> t.state() == Task.State.RUNNING || t.state() == Task.State.RESTORING)
.filter(t -> !corruptedTasks.contains(t.id()))
.collect(Collectors.toSet())
);
} catch (final TaskCorruptedException e) {
Comment thread
ableegoldman marked this conversation as resolved.
log.info("Some additional tasks were found corrupted while trying to commit, these will be added to the " +
"tasks to clean and revive: {}", e.corruptedTasks());
for (final TaskId taskId : e.corruptedTasks()) {
final Task task = tasks.task(taskId);
corruptedActiveTasks.put(task, task.changelogPartitions());
}
}

closeAndRevive(corruptedActiveTasks);
}
Expand Down Expand Up @@ -332,8 +342,8 @@ private void handleCloseAndRecycle(final Set<Task> tasksToRecycle,
// write the checkpoint file.
final Map<TopicPartition, OffsetAndMetadata> offsets = task.prepareCommit();
if (!offsets.isEmpty()) {
log.error("Task {} should has been committed when it was suspended, but it reports non-empty " +
"offsets {} to commit; it means it fails during last commit and hence should be closed dirty",
log.error("Task {} should have been committed when it was suspended, but it reports non-empty " +
"offsets {} to commit; this means it failed during last commit and hence should be closed dirty",
task.id(), offsets);

tasksToCloseDirty.add(task);
Expand Down Expand Up @@ -509,41 +519,62 @@ void handleRevocation(final Collection<TopicPartition> revokedPartitions) {
prepareCommitAndAddOffsetsToMap(commitNeededActiveTasks, consumedOffsetsPerTask);
}

// even if commit failed, we should still continue and complete suspending those tasks,
// so we would capture any exception and throw
// even if commit failed, we should still continue and complete suspending those tasks, so we would capture
// any exception and rethrow it at the end
final Set<TaskId> corruptedTasks = new HashSet<>();
try {
commitOffsetsOrTransaction(consumedOffsetsPerTask);
} catch (final RuntimeException e) {
log.error("Exception caught while committing those revoked tasks " + revokedActiveTasks, e);
firstException.compareAndSet(null, e);
}

// only try to complete post-commit if committing succeeded;
// we enforce checkpointing upon suspending a task: if it is resumed later we just
// proceed normally, if it is going to be closed we would checkpoint by then
if (firstException.get() == null) {
for (final Task task : revokedActiveTasks) {
try {
task.postCommit(true);
} catch (final RuntimeException e) {
log.error("Exception caught while post-committing task " + task.id(), e);
firstException.compareAndSet(null, e);
// If we hit a TaskCorruptedException, we should just handle the cleanup for those corrupted tasks right here
if (e instanceof TaskCorruptedException) {
Comment thread
ableegoldman marked this conversation as resolved.
Outdated
corruptedTasks.addAll(((TaskCorruptedException) e).corruptedTasks());
final Map<Task, Collection<TopicPartition>> corruptedTasksWithChangelogs = new HashMap<>();
for (final TaskId taskId : corruptedTasks) {
final Task task = tasks.task(taskId);
task.markChangelogAsCorrupted(task.changelogPartitions());
corruptedTasksWithChangelogs.put(task, task.changelogPartitions());
}
closeAndRevive(corruptedTasksWithChangelogs);
} else {
// TODO: KIP-572 need to handle TimeoutException, may be rethrown from committing offsets under ALOS
// currently we just let the thread die but we can probably just close those tasks as dirty and proceed
firstException.compareAndSet(null, e);
}
}

if (shouldCommitAdditionalTasks) {
for (final Task task : commitNeededActiveTasks) {
// only try to complete post-commit if committing succeeded, or if we hit a TaskCorruptedException then we
Comment thread
ableegoldman marked this conversation as resolved.
Outdated
// can still checkpoint the uncorrupted tasks (if any)
// we enforce checkpointing upon suspending a task: if it is resumed later we just proceed normally, if it is
// going to be closed we would checkpoint by then
if (firstException.get() == null || !corruptedTasks.isEmpty()) {
for (final Task task : revokedActiveTasks) {
if (!corruptedTasks.contains(task.id())) {
try {
// for non-revoking active tasks, we should not enforce checkpoint
// since if it is EOS enabled, no checkpoint should be written while
// the task is in RUNNING tate
task.postCommit(false);
task.postCommit(true);
} catch (final RuntimeException e) {
log.error("Exception caught while post-committing task " + task.id(), e);
firstException.compareAndSet(null, e);
}
}
}

if (shouldCommitAdditionalTasks) {
for (final Task task : commitNeededActiveTasks) {
if (!corruptedTasks.contains(task.id())) {
try {
// for non-revoking active tasks, we should not enforce checkpoint
// since if it is EOS enabled, no checkpoint should be written while
// the task is in RUNNING tate
task.postCommit(false);
} catch (final RuntimeException e) {
log.error("Exception caught while post-committing task " + task.id(), e);
firstException.compareAndSet(null, e);
}
}
}
}
}

for (final Task task : revokedActiveTasks) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,6 @@ public void suspend() {

task00.setChangelogOffsets(singletonMap(t1p0, 0L));
taskManager.handleCorruption(singleton(taskId00));
assertThat(task00.commitPrepared, is(true));
assertThat(task00.state(), is(Task.State.CREATED));
assertThat(task00.partitionsForOffsetReset, equalTo(taskId00Partitions));
assertThat(taskManager.activeTaskMap(), is(singletonMap(taskId00, task00)));
Expand Down Expand Up @@ -718,7 +717,6 @@ public void shouldCommitNonCorruptedTasksOnTaskCorruptedException() {
topologyBuilder.addSubscribedTopicsFromAssignment(anyObject(), anyString());
expectLastCall().anyTimes();
expectRestoreToBeCompleted(consumer, changeLogReader);
consumer.commitSync(eq(emptyMap()));
expect(consumer.assignment()).andReturn(taskId00Partitions);
replay(activeTaskCreator, topologyBuilder, consumer, changeLogReader);

Expand All @@ -731,7 +729,6 @@ public void shouldCommitNonCorruptedTasksOnTaskCorruptedException() {
corruptedTask.setChangelogOffsets(singletonMap(t1p0, 0L));
taskManager.handleCorruption(singleton(taskId00));

assertTrue(nonCorruptedTask.commitPrepared);
assertThat(nonCorruptedTask.partitionsForOffsetReset, equalTo(Collections.emptySet()));
assertThat(corruptedTask.partitionsForOffsetReset, equalTo(taskId00Partitions));

Expand Down