[ 
https://issues.apache.org/jira/browse/FLINK-31006?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18113926#comment-18113926
 ] 

Martijn Visser commented on FLINK-31006:
----------------------------------------

The bounded FileSource and NumberSequenceSource do not carry this state at all. 
Their enumerators
are pull-based: {{StaticFileSplitEnumerator.addReader}} does nothing, and 
{{handleSplitRequest}}
either assigns the next split or calls {{signalNoMoreSplits}} for that subtask, 
recomputed from the
assigner on every request. There is nothing to lose across a restore, so the 
first split request
after recovery answers correctly. {{IteratorSourceEnumerator}} is the same 
shape and says so in
{{addReader}}: it deliberately assigns nothing on registration and waits for 
the reader's explicit
request.

The Pulsar source is the closer comparison, because it is push-based like 
Kafka. It does not have
this bug, and the reason is precisely what this fix changes.
{{SplitAssignerImpl.registerTopicPartitions}} sets {{initialized = true}} 
unconditionally at the end
of every discovery, whether or not the fetched set contained anything new, and
{{PulsarSourceEnumerator}} calls it on every discovery with no emptiness guard. 
Its
{{noMoreSplits(reader)}} is then derived as
{{!enablePartitionDiscovery && initialized && 
!pendingPartitionSplits.containsKey(reader)}}. So the
nearest neighbour of the Kafka enumerator already does what this fix makes 
Kafka do. That also
confirms the 2023 assessment that the Pulsar component on this ticket can be 
dropped, from the code
rather than from the {{StopCursor}} argument given at the time.

The Kafka source pushes splits eagerly too, and its {{handleSplitRequest}} is 
empty. Because nothing
ever asks, the enumerator has to decide for itself when the input is finished, 
and it remembers that
in {{noMoreNewPartitionSplits}}, which is derived state that never enters the 
checkpoint. That is
the bug, and it is specific to push-based enumerators.

That argues against snapshotting {{noMoreSplitsAssignment}} in 
{{SourceReaderBase}}: pull-based
sources need no reader-side memory, and reader state is redistributed on a 
rescale, so the flag
would follow the wrong subtask.

It also rules out the cheapest enumerator-side variant, which is to derive the 
flag from the
{{initialDiscoveryFinished}} value that is already checkpointed and signal 
straight from
{{addReader}}. Measured on a restored bounded enumerator whose state holds one 
topic while a second
topic appeared while the job was down, with the reader registering before the 
post-restore
discovery completes, the event order for that reader is:

{noformat}
[signalNoMoreSplits:0, assignSplits:0, signalNoMoreSplits:0]
{noformat}

The reader is told the input ended and is assigned a partition afterwards. That 
is what
apache/flink#21909 was rejected for. The same variant also leaves the 
fresh-start half of the bug
unfixed, because {{initialDiscoveryFinished}} is false there.

Waiting for the discovery callback and signalling from 
{{handlePartitionSplitChanges}} keeps the
assignment before the signal in both registration orders and needs no state 
format change.

## Evidence behind it

- `StaticFileSplitEnumerator` and `IteratorSourceEnumerator` read at 
`~/Developer/flink`.
- Pulsar read from `apache/flink-connector-pulsar` on GitHub: 
`SplitAssignerImpl.java:77-79`
  (unconditional `initialized = true`), `:117-121` (derived `noMoreSplits`), 
`:124-126`
  (`initialized` is not snapshotted), and `PulsarSourceEnumerator.java:211-212` 
(unguarded call).
- Ordering measured with a recording `MockSplitEnumeratorContext` subclass; test
  `testRestoredBoundedEnumeratorAssignsBeforeItSignals`, which passes on the 
committed fix and
  fails under the derived-flag variant with the trace above.
- Under the derived-flag variant, `KafkaSourceEnumeratorTest` is 26 tests with 
2 failures: the
  ordering test and `testBoundedSourceWithoutPartitionsSignalsNoMoreSplits`. It 
does pass the
  headline restore test, which is why the shortcut looks attractive.

> job is not finished when using pipeline mode to run bounded source like kafka
> -----------------------------------------------------------------------------
>
>                 Key: FLINK-31006
>                 URL: https://issues.apache.org/jira/browse/FLINK-31006
>             Project: Flink
>          Issue Type: Bug
>          Components: Connectors / Kafka
>    Affects Versions: 2.1.0
>            Reporter: Jacky Lau
>            Assignee: Martijn Visser
>            Priority: Major
>              Labels: pull-request-available
>             Fix For: kafka-5.1.0, kafka-4.0.2, kafka-5.0.1, kafka-3.4.1
>
>         Attachments: image-2023-02-10-13-20-52-890.png, 
> image-2023-02-10-13-23-38-430.png, image-2023-02-10-13-24-46-929.png, 
> image-2023-03-04-01-04-18-658.png, image-2023-03-04-01-05-25-335.png, 
> image-2023-03-04-01-07-04-927.png, image-2023-03-04-01-07-36-168.png, 
> image-2023-03-04-01-08-29-042.png, image-2023-03-04-01-09-24-199.png
>
>
> when i do failover works like kill jm/tm when using  pipeline mode to run 
> bounded source like kafka, i found job is not finished, when every partition 
> data has consumed.
>  
> After dig into code, i found this logical not run when JM recover. the 
> partition infos are not changed. so noMoreNewPartitionSplits is not set to 
> true. then this will not run 
>  
> !image-2023-02-10-13-23-38-430.png!
>  
> !image-2023-02-10-13-24-46-929.png!



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to