Skip to content

[Pipe] Fix historical TsFile schema recovery race - #18314

Open
Caideyipi wants to merge 1 commit into
masterfrom
fix/pipe-historical-schema-race
Open

[Pipe] Fix historical TsFile schema recovery race#18314
Caideyipi wants to merge 1 commit into
masterfrom
fix/pipe-historical-schema-race

Conversation

@Caideyipi

@Caideyipi Caideyipi commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Description

Problem and observed behavior

Historical Pipe events from ConfigRegion, SchemaRegion, and DataRegion are transferred independently. A historical TsFile can therefore reach the receiver before the schema and template events that describe it, making the result dependent on event arrival order.

The timing-dependent failure is as follows:

  • The replicated data and all three expected devices are already visible on the receiver.
  • SHOW PATHS SET DEVICE TEMPLATE aligned_template does not return the expected root.sg_aligned.device_aligned.
  • The receiver log reports that setting aligned_template on root.sg_aligned.device_aligned failed because ordinary timeseries had already been created under that path.

The early TsFile load auto-creates ordinary timeseries. When the historical template-set event arrives later, it conflicts with those timeseries and the receiver cannot restore the original template binding.

Fix

  • Mark a TsFile transfer as requiring schema readiness only when all of the following are true:
    • the source is the built-in IoTDB source;
    • the sink sends a Pipe request rather than a general write request;
    • the inclusion options contain all schema events required before loading data: ordinary timeseries creation and template create/alter/set/activate.
  • Carry this marker in V2 TsFile seal parameters through synchronous Thrift, asynchronous Thrift, and AirGap sinks.
  • For a marked transfer, force schema verification and disable schema auto-creation for that individual load.
  • Treat missing schema as temporary unavailability so Pipe retries the TsFile after the corresponding schema/template events arrive.
  • Preserve the per-load option through the Active Load path used by asynchronous loading.
  • Verify existing schema under the schema-deletion read lock to avoid racing with deletion while auto-creation is disabled.

This avoids imposing cross-region transfer ordering: data loading simply waits and retries until the schema history has been applied.

Compatibility

The new behavior is opt-in through an internal system parameter and defaults to disabled on the wire. Existing behavior is preserved for external sources, incomplete schema inclusion, general-write requests, mark-as-pipe-request=false, legacy requests, and ordinary LOAD TSFILE operations. The existing default that permits per-load schema auto-creation also remains unchanged unless the receiver gets the new marker.

Tests

  • Added focused unit coverage for parameter gating, V2 request serialization, synchronous/asynchronous receiver configuration, retry classification, and Active Load attribute persistence.
  • Extended IoTDBPipeAutoConflictIT to assert that root.sg_aligned.device_aligned is bound to aligned_template on the receiver.
  • Focused test run: OK (76 tests) across 6 test classes.
  • Spotless, whitespace checks, and isolated compilation of the affected sources passed.
  • A full local Maven/IT run could not reach the target IT because this checkout has unrelated stale Freemarker-generated sources and an incompatible template-node artifact.

This PR has:

  • been self-reviewed.
    • concurrent write
  • added comments explaining non-obvious intent.
  • added or updated unit tests for the new code paths.
  • updated integration-test coverage.

Key changed/added classes (or packages if there are too many classes) in this PR
  • PipeDataNodeTaskBuilder: determines whether a Pipe has complete schema history and injects the internal wait marker.
  • PipeTransferTsFileSealWithModReq and DataRegion sinks: propagate the marker across all V2 transfer paths.
  • IoTDBDataNodeReceiver: configures marked sync and async loads to verify without auto-creating schema.
  • LoadTsFileAnalyzer, TreeSchemaAutoCreatorAndVerifier, and SchemaValidator: support per-load schema auto-creation control and retryable missing-schema handling.
  • Active Load helpers/configuration: persist the per-load option across asynchronous handoff.

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
E Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@codecov

codecov Bot commented Jul 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 61.65414% with 51 lines in your changes missing coverage. Please review.
✅ Project coverage is 42.93%. Comparing base (892dbd8) to head (4cc75a8).

Files with missing lines Patch % Lines
...eceiver/protocol/thrift/IoTDBDataNodeReceiver.java 33.33% 12 Missing ⚠️
...ueryengine/plan/analyze/schema/ISchemaFetcher.java 0.00% 7 Missing ⚠️
...able/request/PipeTransferTsFileSealWithModReq.java 66.66% 5 Missing ⚠️
...ink/protocol/airgap/IoTDBDataRegionAirGapSink.java 20.00% 4 Missing ⚠️
...hrift/async/handler/PipeTransferTsFileHandler.java 0.00% 4 Missing ⚠️
...eryengine/plan/analyze/schema/SchemaValidator.java 0.00% 4 Missing ⚠️
...pe/agent/task/builder/PipeDataNodeTaskBuilder.java 88.00% 3 Missing ⚠️
...ngine/plan/statement/crud/LoadTsFileStatement.java 70.00% 3 Missing ⚠️
.../protocol/thrift/sync/IoTDBDataRegionSyncSink.java 0.00% 2 Missing ⚠️
...ryengine/plan/analyze/load/LoadTsFileAnalyzer.java 81.81% 2 Missing ⚠️
... and 4 more
Additional details and impacted files
@@             Coverage Diff              @@
##             master   #18314      +/-   ##
============================================
- Coverage     43.10%   42.93%   -0.17%     
  Complexity      374      374              
============================================
  Files          5362     5363       +1     
  Lines        381676   381774      +98     
  Branches      49568    49585      +17     
============================================
- Hits         164504   163903     -601     
- Misses       217172   217871     +699     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment on lines +117 to +118
private final boolean isAutoCreateSchemaAllowed;
private final boolean isAutoCreateSchema;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too confusing, give better names.

Comment on lines +126 to +139
default ISchemaTree fetchSchemaList(
final List<PartialPath> devicePaths,
final List<String[]> measurementsList,
final MPPQueryContext context) {
DataNodeSchemaLockManager.getInstance()
.takeReadLock(context, SchemaLockType.VALIDATE_VS_DELETION_TREE);
final PathPatternTree patternTree = new PathPatternTree();
for (int i = 0; i < devicePaths.size(); i++) {
for (final String measurement : measurementsList.get(i)) {
patternTree.appendFullPath(devicePaths.get(i), measurement);
}
}
return fetchSchema(patternTree, true, context, true);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is the lock released?
Add a comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants