Rion Williams created FLINK-41505:
-------------------------------------

             Summary: Loss-tolerant OperatorEvent that hits a finished task 
fails the coordinator checkpoint
                 Key: FLINK-41505
                 URL: https://issues.apache.org/jira/browse/FLINK-41505
             Project: Flink
          Issue Type: Bug
          Components: Runtime / Coordination
    Affects Versions: 2.1.3, 2.2.1, 2.3.0
            Reporter: Rion Williams
             Fix For: 2.5.0


h3. Problem

FLINK-37670 made {{WatermarkAlignmentEvent}} loss tolerant 
({{OperatorEvent#isLossTolerant}}) and has the {{SourceCoordinator}} keep 
sending it after the enumerator has no more splits. 
{{SubtaskGatewayImpl#sendEvent}} accordingly skips the task failover when such 
an event fails with {{TaskNotRunningException}}.

However, the future of that event is still registered in the 
{{IncompleteFuturesTracker}} and completes exceptionally. If a coordinator 
checkpoint is waiting for pending events at that moment, 
{{OperatorCoordinatorHolder#completeCheckpointOnceEventsAreDone}} fails it:

{noformat}
Coordinator checkpoint <id> for coordinator <op> is awaiting 1 pending events
...
org.apache.flink.util.FlinkException: Failing OperatorCoordinator checkpoint 
because some OperatorEvents before this checkpoint barrier were not received by 
the target tasks.
{noformat}

So an event loss that the gateway treats as harmless still fails the checkpoint.

h3. When it happens

Watermark alignment is enabled, a source subtask finishes while an alignment 
announcement (every {{updateInterval}}) is in flight to it, and a coordinator 
checkpoint is taken before that delivery fails. The window is when source 
subtasks finish, which is also when coordinator snapshots tend to be taken:
* streaming with bounded or finishing sources (checkpoints after tasks 
finished): a failed checkpoint, which counts towards the tolerable checkpoint 
failures;
* batch job recovery: {{DefaultBatchJobRecoveryHandler#onExecutionFinished}} 
snapshots the coordinators (checkpoint id -1) when an execution finishes, so 
the snapshot future fails while the {{ExecutionVertexFinishedEvent}} is written.

We found it through a job that takes a single coordinator snapshot right after 
the sources reach end of input and cannot retry it, so the race failed the 
whole job in about 1 in 5 runs.

h3. Reproduction

Deterministic unit test against {{OperatorCoordinatorHolderTest}}. It fails on 
master at the last assertion:

{code:java}
@Test
void testCheckpointSucceedsIfLossTolerantEventFindsTaskNotRunning() throws 
Exception {
    CompletableFuture<Acknowledge> eventSendingResult = new 
CompletableFuture<>();
    final EventReceivingTasks tasks =
            
EventReceivingTasks.createForRunningTasksWithRpcResult(eventSendingResult);
    final OperatorCoordinatorHolder holder =
            createCoordinatorHolder(tasks, TestingOperatorCoordinator::new);

    // Send one loss-tolerant event without finishing it.
    CompletableFuture<Acknowledge> sendResult =
            getCoordinator(holder).getSubtaskGateway(0).sendEvent(new 
TestOperatorEvent(0, true));

    // Trigger one checkpoint.
    CompletableFuture<byte[]> checkpointResult = new CompletableFuture<>();
    holder.checkpointCoordinator(1, checkpointResult);
    getCoordinator(holder).getLastTriggeredCheckpoint().complete(new byte[0]);

    // The target task finished before the event reached it.
    eventSendingResult.completeExceptionally(
            new FlinkException(new TaskNotRunningException("test")));

    assertThat(sendResult).isCompletedExceptionally();
    assertThat(checkpointResult).isCompleted(); // fails: completed 
exceptionally
}
{code}

h3. Proposed fix

In {{SubtaskGatewayImpl#sendEvent}}, track a future for the checkpoint that 
treats a loss-tolerant event failing with {{TaskNotRunningException}} as 
delivered, i.e. the same condition that already skips the failover. The future 
returned to the caller still completes exceptionally, so 
{{SubtaskGatewayImplTest#optionalEventsIgnoreTaskNotRunning}} is unchanged. It 
is a small change in {{SubtaskGatewayImpl}} plus the test above; I have a patch 
ready.




--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to