[ 
https://issues.apache.org/jira/browse/FLINK-41313?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

liting liu updated FLINK-41313:
-------------------------------
    Description: 
h3. Problem

The Fluss pipeline source may fail to resume data consumption when restoring a 
checkpoint that references partitions which have been dropped or expired. The 
logical table and other partitions can still exist, but the source retains 
obsolete partition splits and keeps requesting metadata for their old partition 
IDs. The job can remain RUNNING while valid partitions stop making progress.

The same missing partition-retirement handling also affects a running source 
when a partition disappears while its logical table remains subscribed.

h3. Reproduction

# Create a partitioned Fluss PK table with at least two partitions and multiple 
buckets. Enable periodic discovery in the CDC pipeline.
# Start the pipeline, consume data from both partitions, and complete a 
retained externalized checkpoint.
# Cancel the whole job and wait for termination.
# Drop one partition through the Fluss Admin API, or allow it to expire. Keep 
the logical table and another partition available.
# Write new rows to the surviving partition.
# Restore the whole job from the earlier checkpoint with the same operator 
UIDs. The source should skip the absent partition and continue from the 
surviving partition's checkpoint position; obsolete partition IDs must not 
block consumption.

h3. Root cause

* Discovery reconciles logical-table subscriptions and initializes new physical 
partitions, but does not retire disappeared partitions from an otherwise 
subscribed table.
* Enumerator assigned/pending state can therefore retain obsolete physical 
paths. A table-level subscription snapshot does not distinguish a valid 
restored split from a split belonging to a deleted partition.
* The obsolete split can reach the SDK scanner, which keeps attempting metadata 
refreshes for the missing numeric partition ID. Synchronous metadata waits 
consume fetch time and delay valid buckets handled by the same reader.

h3. Proposed fix

* Reconcile physical partitions only after a successful complete discovery. A 
failed or incomplete metadata query must not imply partition deletion.
* Clear obsolete coordinator assignment/pending state before publishing the 
complete physical-partition inventory to readers, including newly registered or 
restored readers.
* Keep restored splits staged until the inventory arrives, filter absent 
partitions before SDK subscription, and reject obsolete initialization results 
or returned splits using current bucket identities.
* Execute precise SDK partition/bucket unsubscribe and snapshot cancellation on 
the fetcher thread. Finish the affected splits through normal reader state 
cleanup while preserving surviving partitions and logical-table 
schema/resources.
* Preserve existing checkpoint serializer versions and split IDs. Same-name 
partition recreation with a new physical ID requires separate generation-aware 
handling.


  was:
h3. Checkpoint recovery failure

A completed checkpoint can still reference a Fluss partition that is dropped or 
expires before the entire CDC job is restored. The source must discard that 
absent partition before SDK subscription and resume the surviving partitions 
from their checkpoint positions. Otherwise recovery can remain blocked on 
repeated metadata requests for obsolete partition IDs, even when the job status 
is RUNNING.

Reproduction scenario:
# Create a partitioned Fluss PK table with two partitions and multiple buckets; 
start the CDC pipeline and consume both partitions.
# Complete an externalized checkpoint, then cancel the entire job and wait for 
termination.
# Physically drop one partition with the Admin API and verify the partition is 
absent.
# Write new rows to the surviving partition while the job is stopped.
# Start a new job from the exact earlier checkpoint. It should consume the new 
survivor rows without replaying the initial rows and continue completing 
checkpoints.

h3. Proposed fix

A proposed fix reconciles coordinator assignments with successful complete 
partition discovery, sends complete physical inventories to readers, and 
filters restored splits before SDK subscription. Active obsolete splits are 
unsubscribed/cancelled on the fetcher thread and finished through the normal 
reader state-cleanup path. Surviving partition and logical-table resources are 
preserved; existing checkpoint serializer versions are unchanged.

The full checkpoint -> whole-job cancellation -> actual dropPartition -> 
restore-from-the-same-checkpoint scenario passed in earliest and full startup 
modes on both Flink 1.20.3 / Java 11 and Flink 2.2.0 / Java 17 (4/4 
executions). The test verifies the actual restored checkpoint path, exact 
survivor rows without baseline replay, two further successful checkpoints, and 
RUNNING status with automatic failure restart disabled. This is local embedded 
Flink/Fluss validation, not deployment validation.

* [Checkpoint recovery 
regression|https://github.com/litiliu/flink-cdc/commit/4cd5896485522d64af32730cb33cba783f9bbaeb]
* [Partition retirement 
fix|https://github.com/litiliu/flink-cdc/commit/18499592a0e2b2f508c3e7aeba8168ebf21651b0]

Same-name partition recreation with a new physical ID, recovery during an 
in-progress KV snapshot, and deletion racing after successful discovery remain 
follow-up boundaries of this proposed fix.

h3. Problem

The Fluss pipeline source does not retire a dropped or expired physical 
partition while its logical table remains in the TableDiscoverer subscription.

After the partition disappears from Fluss metadata, readers can retain its 
splits and keep requesting metadata for the old partition ID. LogFetcher 
repeatedly reports:

{code}
Receive PartitionNotExistException when update metadata, ignore it
org.apache.fluss.exception.PartitionNotExistException: The partition id 
'<expired-id>' does not exist or you don't have permission to access it.
{code}

The job can remain RUNNING and continue checkpointing while source fetcher 
threads repeatedly wait in MetadataUtils.sendMetadataRequestAndRebuildCluster / 
LogFetcher.checkAndUpdateMetadata. This consumes fetch time and delays other 
valid buckets handled by the same reader.

h3. Scope and current-code check

Checked Apache Flink CDC master at db45d06a1e35bc6be87f7b58913c768f8f299d3e.

FLINK-40575 / PR #4527 implements logical-table unsubscription. Its 
table-removal detection compares TablePath sets. If a table stays subscribed 
and only one partition disappears, no table-removal event is generated. The 
existing removeTables cleanup therefore does not retire that partition.

The current bucket-discovery path initializes new buckets but does not 
reconcile removed physical partitions. The reader events and cleanup entry 
points still operate at logical-table granularity.

* [Enumerator: subscription update and table-level 
removal|https://github.com/apache/flink-cdc/blob/db45d06a1e35bc6be87f7b58913c768f8f299d3e/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-fluss/src/main/java/org/apache/flink/cdc/connectors/fluss/source/enumerator/FlussSourceEnumerator.java#L294-L367]
* [Reader: table subscription 
events|https://github.com/apache/flink-cdc/blob/db45d06a1e35bc6be87f7b58913c768f8f299d3e/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-fluss/src/main/java/org/apache/flink/cdc/connectors/fluss/source/reader/FlussSourceReader.java#L179-L208]
* [Split reader: existing whole-table 
cleanup|https://github.com/apache/flink-cdc/blob/db45d06a1e35bc6be87f7b58913c768f8f299d3e/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-fluss/src/main/java/org/apache/flink/cdc/connectors/fluss/source/reader/FlussSplitReader.java#L410-L445]

h3. Reproduction / regression-test scenario

# Create a partitioned Fluss table with multiple buckets and at least two live 
partitions.
# Start a streaming Fluss pipeline source and wait until readers subscribe to 
both partitions. Keep the table in the discoverer's subscription throughout the 
test.
# Drop one existing partition, or allow it to expire.
# Allow a successful partition discovery cycle to observe that the partition is 
absent.
# Verify whether the old partition's buckets are unsubscribed and its split 
state is retired while the remaining partitions continue to be read.
# Take a checkpoint and restore. Verify that a still-absent partition is not 
assigned or subscribed again.

The repeated metadata-request behavior was observed in a deployed CDC 
3.7-SNAPSHOT / Fluss 1.1-SNAPSHOT job without a job restart during partition 
rotation. The upstream code was checked at the commit above; automated 
regression coverage and local validation of the proposed fix have now been 
added as described above.

h3. Expected behavior

* Detect removed physical partitions after a successful authoritative metadata 
discovery, independently of logical-table subscription changes.
* Notify the affected readers and invoke the SDK's precise partition/bucket 
unsubscribe operation.
* Mark removed splits finished through the normal reader cleanup path and 
reconcile enumerator assignment/pending state so checkpoint recovery does not 
revive absent partitions.
* Continue consuming remaining partitions and other tables. Do not emit a 
DropTableEvent or remove the sink table merely because one source partition 
expired.
* Do not treat a failed or incomplete metadata listing as an authoritative 
partition deletion.
* Handle later partition re-creation using its physical partition identity, 
without reviving stale split offsets.

h3. Related work

* FLINK-40575 / https://github.com/apache/flink-cdc/pull/4527 covers 
whole-table unsubscription, not this single-partition lifecycle.
* https://github.com/apache/fluss/issues/3466 discusses repeated metadata 
requests for expired partitions and SDK/server mitigations. This issue tracks 
the CDC connector's partition-removal and checkpoint-cleanup lifecycle.
* https://github.com/apache/fluss/issues/2202 proposes per-partition metadata 
failure reporting; it does not provide the missing CDC cleanup flow.



> Fluss pipeline source fails to recover from checkpoints referencing dropped 
> or expired partitions
> -------------------------------------------------------------------------------------------------
>
>                 Key: FLINK-41313
>                 URL: https://issues.apache.org/jira/browse/FLINK-41313
>             Project: Flink
>          Issue Type: Bug
>          Components: Flink CDC
>            Reporter: liting liu
>            Priority: Major
>
> h3. Problem
> The Fluss pipeline source may fail to resume data consumption when restoring 
> a checkpoint that references partitions which have been dropped or expired. 
> The logical table and other partitions can still exist, but the source 
> retains obsolete partition splits and keeps requesting metadata for their old 
> partition IDs. The job can remain RUNNING while valid partitions stop making 
> progress.
> The same missing partition-retirement handling also affects a running source 
> when a partition disappears while its logical table remains subscribed.
> h3. Reproduction
> # Create a partitioned Fluss PK table with at least two partitions and 
> multiple buckets. Enable periodic discovery in the CDC pipeline.
> # Start the pipeline, consume data from both partitions, and complete a 
> retained externalized checkpoint.
> # Cancel the whole job and wait for termination.
> # Drop one partition through the Fluss Admin API, or allow it to expire. Keep 
> the logical table and another partition available.
> # Write new rows to the surviving partition.
> # Restore the whole job from the earlier checkpoint with the same operator 
> UIDs. The source should skip the absent partition and continue from the 
> surviving partition's checkpoint position; obsolete partition IDs must not 
> block consumption.
> h3. Root cause
> * Discovery reconciles logical-table subscriptions and initializes new 
> physical partitions, but does not retire disappeared partitions from an 
> otherwise subscribed table.
> * Enumerator assigned/pending state can therefore retain obsolete physical 
> paths. A table-level subscription snapshot does not distinguish a valid 
> restored split from a split belonging to a deleted partition.
> * The obsolete split can reach the SDK scanner, which keeps attempting 
> metadata refreshes for the missing numeric partition ID. Synchronous metadata 
> waits consume fetch time and delay valid buckets handled by the same reader.
> h3. Proposed fix
> * Reconcile physical partitions only after a successful complete discovery. A 
> failed or incomplete metadata query must not imply partition deletion.
> * Clear obsolete coordinator assignment/pending state before publishing the 
> complete physical-partition inventory to readers, including newly registered 
> or restored readers.
> * Keep restored splits staged until the inventory arrives, filter absent 
> partitions before SDK subscription, and reject obsolete initialization 
> results or returned splits using current bucket identities.
> * Execute precise SDK partition/bucket unsubscribe and snapshot cancellation 
> on the fetcher thread. Finish the affected splits through normal reader state 
> cleanup while preserving surviving partitions and logical-table 
> schema/resources.
> * Preserve existing checkpoint serializer versions and split IDs. Same-name 
> partition recreation with a new physical ID requires separate 
> generation-aware handling.



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

Reply via email to