Skip to content

[Feature][Connector-V2][Oracle-CDC] Add SCN specific startup#11171

Open
goutamadwant wants to merge 4 commits into
apache:devfrom
goutamadwant:GH-11041
Open

[Feature][Connector-V2][Oracle-CDC] Add SCN specific startup#11171
goutamadwant wants to merge 4 commits into
apache:devfrom
goutamadwant:GH-11041

Conversation

@goutamadwant

Copy link
Copy Markdown
Contributor

Purpose of this pull request

Fixes #11041.

This PR adds Oracle CDC support for starting from a user-provided SCN with:

  • startup.mode = specific
  • startup.specific-offset.scn = 123456789

The configured SCN is mapped into the existing Oracle redo-log offset model, so the incremental split uses the same offset shape as the current latest and timestamp startup paths. Invalid combinations fail early, including missing SCN, non-positive SCN, or file/position offsets with Oracle specific startup.

The Oracle CDC docs are also updated to describe SCN based specific startup instead of binlog file/position options.

Does this PR introduce any user-facing change?

Yes. Oracle CDC users can now configure SCN based specific startup with startup.specific-offset.scn.

The previous Oracle CDC docs mentioned binlog file/position specific startup, but the Oracle connector does not use binlog file/position offsets. This PR documents and validates the Oracle-specific SCN config instead.

If the configured SCN is no longer available to the selected Oracle log mining backend, startup should fail from the normal Oracle/Debezium recovery path instead of silently falling back to another startup mode.

How was this patch tested?

Added unit coverage for:

  • requiring startup.specific-offset.scn when startup.mode = specific
  • rejecting non-positive SCN values
  • mapping the configured SCN into RedoLogOffset
  • preserving the SCN-derived startup offset through IncrementalSplitState restore
  • rejecting startup.specific-offset.scn outside specific startup mode
  • rejecting file/position offsets for Oracle specific startup

Verified locally with:

JAVA_HOME=$(/usr/libexec/java_home -v 11) PATH="$JAVA_HOME/bin:$PATH" ./mvnw -pl seatunnel-connectors-v2/connector-cdc/connector-cdc-oracle -Dtest=OracleIncrementalSourceFactoryTest test

JAVA_HOME=$(/usr/libexec/java_home -v 11) PATH="$JAVA_HOME/bin:$PATH" ./mvnw -pl seatunnel-connectors-v2/connector-cdc/connector-cdc-oracle -DfailIfNoTests=false package

Check list

@DanielLeens DanielLeens left a comment

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.

Thanks for working on this! I reviewed the full current diff, traced the Oracle CDC startup path into the shared CDC startup contract, and I don't think the current implementation is merge-ready yet.

What this PR solves

  • User pain: Oracle CDC users may want to start from a specific SCN instead of only initial, latest, or timestamp-based startup.
  • Fix approach: add a new Oracle-specific startup.specific-offset.scn option and translate it into the startup config used by OracleIncrementalSource.
  • One-line summary: the feature direction is useful, but the current head does not actually fit the shared CDC startup contract that the Oracle source still depends on.

Runtime chain I checked

Oracle CDC source construction
  -> OracleIncrementalSource.buildStartupConfig(...) [OracleIncrementalSource.java:118-135]
      -> reads `startup.specific-offset.scn`
      -> builds a RedoLogOffset-shaped map
      -> returns new StartupConfig(startupMode, specificOffset)

Shared CDC startup contract
  -> StartupConfig [connector-cdc-base/.../StartupConfig.java:30-55]
      -> stores only {specificOffsetFile, specificOffsetPos, timestamp}
      -> SPECIFIC path calls offsetFactory.specific(specificOffsetFile, specificOffsetPos)

Findings

Issue 1: the new Oracle-specific SCN startup path does not match the shared StartupConfig contract

  • Location: seatunnel-connectors-v2/connector-cdc/connector-cdc-oracle/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/oracle/source/OracleIncrementalSource.java:131-135, seatunnel-connectors-v2/connector-cdc/connector-cdc-base/src/main/java/org/apache/seatunnel/connectors/cdc/base/config/StartupConfig.java:30-55
  • Why this is a problem:
    The Oracle path now tries to hand a Map<String, String>-style redo-log offset into StartupConfig, but the shared base class still models SPECIFIC startup only as file + pos. Its runtime path still delegates to offsetFactory.specific(specificOffsetFile, specificOffsetPos).
  • Risk:
    On the current head, the new option is not actually wired through a coherent startup contract. At best this is incomplete; at worst it leaves the source in a non-compilable or non-runnable state depending on how the constructor mismatch is resolved.
  • Better fix:
    Either extend the base startup/offset contract explicitly so Oracle can carry a structured specific offset end to end, or keep the SCN-specific handling inside the Oracle-specific path instead of forcing it through the generic file + pos startup model.
  • Severity: High
  • Already raised by others: No

Issue 2: the new option surface implies a working Oracle-specific offset shape, but the shared runtime still only understands generic specific offsets

  • Location: seatunnel-connectors-v2/connector-cdc/connector-cdc-oracle/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/oracle/source/OracleIncrementalSourceOptions.java:62-66, seatunnel-connectors-v2/connector-cdc/connector-cdc-oracle/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/oracle/source/offset/RedoLogOffset.java:36-55
  • Why this is a problem:
    The PR adds startup.specific-offset.scn and builds a RedoLogOffset-shaped map, but there is still no matching shared startup path that consumes {scn, commit_scn, lcr_position} as the normal SPECIFIC startup input.
  • Risk:
    Users get a new documented config surface without a proven end-to-end runtime contract behind it.
  • Better fix:
    Make the Oracle startup contract explicit end to end, then add a regression test that proves a specific-SCN startup reaches the runtime offset factory correctly.
  • Severity: High
  • Already raised by others: No

Compatibility

  • API/config names: additive only.
  • Behavior: not safe to claim as compatible yet, because the new startup mode is not fully connected to the shared CDC startup runtime.
  • Migration: not applicable until the implementation is complete.

Performance and side effects

  • No meaningful CPU / memory concern from the option itself.
  • The real side effect is correctness: a startup option that looks supported but is not fully wired can fail at source startup or during offset construction.

Tests and docs

  • Any tests and docs added around SCN startup are not enough until the runtime startup contract itself is made coherent.
  • I would strongly recommend a focused regression test that proves startup.mode = specific plus SCN reaches the real Oracle offset startup path.

CI

  • The latest Build is red, but the runtime-contract gap above is already a source-level blocker regardless of CI.

Merge conclusion

Conclusion: can merge after fixes

  1. Blocking items
  • Issue 1: complete the Oracle-specific startup contract instead of routing a structured SCN offset through a shared StartupConfig model that still only understands file + pos.
  • Issue 2: prove the new SCN startup option through a real end-to-end startup regression test.
  1. Suggested follow-up
  • Once the contract is settled, keep the docs explicit about exactly which Oracle startup modes are supported and how they map to redo-log offsets.

Happy to take another pass once the Oracle-specific offset shape is wired through a consistent startup path.

@davidzollo davidzollo added the First-time contributor First-time contributor label Jun 23, 2026
@hiSandog

Copy link
Copy Markdown

The Oracle-specific SCN startup path looks much clearer than documenting file/position offsets for Oracle.

One compatibility point to call out: this PR also narrows stop.mode documentation and option handling to never. If existing Oracle CDC users could previously set stop.mode=latest or specific even if it was not meaningful, it may be worth adding a migration note or an explicit validation test that shows the new failure mode is intentional.

@DanielLeens

Copy link
Copy Markdown
Contributor

Thanks, this is a fair compatibility point to raise. I agree that if this PR continues narrowing stop.mode, then a migration note and/or an explicit validation test for the new failure mode would be useful.

That said, on the current head my main blocker is still the earlier runtime-contract gap: the SCN-specific structured offset is not wired through the shared StartupConfig path yet. Once a new code update closes that contract gap, I think the stop.mode compatibility note should be handled in the same patch.

@goutamadwant

Copy link
Copy Markdown
Contributor Author

Hi @DanielLeens @davidzollo I updated the PR based on the review.

Oracle SCN startup now keeps the SCN as a structured specific offset through StartupConfig.specificOffset(Map), so it uses RedoLogOffsetFactory.specific(Map). The existing file/position specific offset path is unchanged.

I also added a focused check that Oracle CDC only exposes StopMode.NEVER.

Verified with:

./mvnw -q -pl seatunnel-connectors-v2/connector-cdc/connector-cdc-base,seatunnel-connectors-v2/connector-cdc/connector-cdc-oracle -Dtest=OracleIncrementalSourceFactoryTest -DfailIfNoTests=false -DskipITs test
./mvnw -q -pl seatunnel-connectors-v2/connector-cdc/connector-cdc-base,seatunnel-connectors-v2/connector-cdc/connector-cdc-oracle -DskipTests -DskipITs package

@DanielLeens DanielLeens left a comment

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.

Thanks for the update, and thanks for following up with the focused startup-contract changes. I re-reviewed the latest head locally from the full Oracle CDC startup path again instead of just looking at the incremental patch, and the main Daniel blocker from the previous round is now closed on the current revision.

What this PR fixes:

  • User pain: Oracle CDC users need a real way to start from a specific Oracle SCN, but the previous path was still shaped around generic file/position-specific startup semantics.
  • Fix approach: keep Oracle-specific SCN startup as a structured offset all the way through StartupConfig.specificOffset(Map) into RedoLogOffsetFactory.specific(Map), and tighten validation so specific mode cannot silently fall back to file/position inputs.
  • In one sentence: this PR turns Oracle-specific startup from a documentation-level idea into a real startup-offset path that reaches the runtime offset factory correctly.

Runtime call chain I checked:

Oracle CDC source construction
  -> IncrementalSource.<init>() [IncrementalSource.java:118-129]
      -> getStartupConfig(readonlyConfig)
          -> OracleIncrementalSource.getOracleStartupConfig(...) [OracleIncrementalSource.java:92-136]
              -> if startup.mode != specific:
                  -> keep the existing StartupConfig(startupMode, file, pos, timestamp) path
              -> if startup.mode == specific:
                  -> reject startup.specific-offset.file / pos
                  -> require startup.specific-offset.scn > 0
                  -> build {scn, commit_scn, lcr_position} map
                  -> StartupConfig.specificOffset(map)

Runtime offset materialization
  -> StartupConfig.getStartupOffset(offsetFactory) [StartupConfig.java:68-86]
      -> SPECIFIC with structured offset
          -> offsetFactory.specific(Map)
              -> RedoLogOffsetFactory.specific(Map) [RedoLogOffsetFactory.java:64-67]
                  -> new RedoLogOffset(offset)

Key findings from the current head:

  • The earlier runtime-contract gap is fixed. Oracle-specific startup is no longer pretending to fit the generic file + pos path; it now uses the structured specific(Map) branch end to end.
  • The factory validation now matches the runtime contract:
    • startup.mode = specific requires startup.specific-offset.scn
    • the SCN must be > 0
    • file/position-specific offsets are explicitly rejected for Oracle-specific startup
  • The new test coverage is pointed at the real contract:
    • OracleIncrementalSourceFactoryTest.java:62-134 covers missing SCN, invalid SCN, wrong mode, and file/position rejection.
    • OracleIncrementalSourceFactoryTest.java:85-108 proves the structured Oracle offset survives IncrementalSplit -> IncrementalSplitState -> toSourceSplit() without losing the SCN payload.
  • Related to @hiSandog's earlier compatibility point about stop.mode: I rechecked origin/dev, and OracleIncrementalSourceOptions.STOP_MODE was already a single-choice never there. So on the latest head, the doc/test update is aligning with the existing runtime boundary rather than introducing a new stop-mode restriction.
  • I do not see API, config-default, protocol, or backward-compatibility regressions in the current implementation.

Test stability:

  • Stable.
  • The added tests are pure config / object-level unit tests with no sleeps, no containers, no network, and no time-sensitive async behavior.

CI note:

  • The current Build failure does not look like an Oracle CDC code regression.
  • I checked the failing fork run behind the check, and the failure is in the website job during node tools/generate-team-pr-contributors.js with: GitHub token not found. Set GITHUB_TOKEN/GH_TOKEN or run gh auth login first.
  • So from Daniel's side, this looks like a workflow/token issue on the fork build path rather than a blocker reopened by the Oracle source changes themselves.

Merge conclusion:

  • Conclusion: mergeable from Daniel's side.
  • Blocking code issues: none in the current revision.
  • Non-blocking suggestions: none.
  • Remaining GitHub item: the failing Build should still be rerun/fixed on the CI side before the PR actually lands, but I do not see evidence that the Oracle CDC code in this PR is the cause.

Overall, the Oracle-specific startup contract now looks coherent end to end, and the latest head closes the main blocker from my previous review.

@DanielLeens

Copy link
Copy Markdown
Contributor

Thanks for the update. I rechecked the current head against the latest dev, and this branch is still behind upstream.

  • base branch: dev
  • head SHA: 685fe47676bb5bb4962cccabecc63a102f2758f1
  • compare status: diverged
  • ahead_by: 2
  • behind_by: 30
  • mergeable_state: unknown
  • CI / merge gate snapshot: failing (failing: Build [failure])

Because the PR is still behind the latest base, any CI result and merge gate signal here is mixed with upstream drift. The lowest-cost next step is to sync with the latest dev and rerun CI first. If anything still fails after the sync, I'm happy to take another look on top of the updated head.

@DanielLeens

Copy link
Copy Markdown
Contributor

Thanks for the update. I rechecked the current head against the latest dev, and the source-level blockers from my previous Daniel review still stand on this branch.

  • base branch: dev
  • head SHA: 685fe47676bb5bb4962cccabecc63a102f2758f1
  • compare status: diverged
  • ahead_by: 2
  • behind_by: 38
  • CI / merge gate snapshot: Build FAILURE

The current failing CI signal does not look actionable on top of this stale head yet, so the lowest-cost next step is to sync with the latest dev and rerun CI first. If anything still fails after the sync, I am happy to take another look on top of the updated head.

@goutamadwant

Copy link
Copy Markdown
Contributor Author

@DanielLeens Synced this branch with latest dev and pushed the rebased branch.

Local checks:

  • OracleIncrementalSourceFactoryTest passes
  • cdc-base + cdc-oracle package check passes
  • broader cdc module test run still hits OracleDdlParserTest.testParseDDLForAddColumn

I checked that parser failure against clean origin/dev as well and it fails there too, so that one does not look introduced by this PR.

@DanielLeens

DanielLeens commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Thanks for the rebase update.

From Daniel's side, the current source revision is still the same Oracle CDC head I already approved (2ddc1bceaf3e875404362235b2071459e0aba839), so I do not have a reopened code-level blocker on the current branch.

What still needs to be cleared before merge is the current GitHub Build gate. On the latest fork run the visible failing job is still Run / Build website, which is outside the Oracle CDC runtime path I reviewed. So the next step is still to get that CI gate green on the rebased branch.

@DanielLeens

DanielLeens commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Thanks for the earlier rebase update. I rechecked the current head against the latest dev and the live merge state.

  • base branch: dev
  • head SHA: 99e5602904299eb7f3c625b1c0f4e2fde9047a4c
  • compare status: diverged
  • ahead_by: 2
  • behind_by: 47
  • mergeable_state: dirty
  • CI / merge gate snapshot: merge conflicts reported by GitHub

From Daniel's side, I still do not see a reopened Oracle-CDC source blocker on the current branch. But GitHub is now reporting merge conflicts against the latest dev, so the next step is to sync with the latest dev, resolve those conflicts, and rerun the checks on the updated head first. Once that is done, I am happy to take another look if anything remains unclear.

Signed-off-by: goutamadwant <workwithgoutam@gmail.com>

# Conflicts:
#	docs/en/connectors/source/Oracle-CDC.md
#	docs/zh/connectors/source/Oracle-CDC.md
@goutamadwant

Copy link
Copy Markdown
Contributor Author

Synced this branch with latest dev and resolved the Oracle CDC docs conflict.

I kept the latest dev wording for the common Oracle CDC options and kept this PR's SCN specific startup option docs. The startup docs still match the runtime contract where Oracle specific startup uses startup.specific-offset.scn.

Local Oracle CDC focused test and package check pass with Java 11.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature][Connector-V2][Oracle-CDC] Add SCN-based specific-offset startup

4 participants