Skip to content

Add ComposedNamedPhysicalExtensionCodec - #24826

Draft
gabotechs wants to merge 1 commit into
mainfrom
gabotechs/composed-named-physical-extension-codec
Draft

Add ComposedNamedPhysicalExtensionCodec#24826
gabotechs wants to merge 1 commit into
mainfrom
gabotechs/composed-named-physical-extension-codec

Conversation

@gabotechs

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

  • Closes #.

Rationale for this change

The ComposedPhysicalExtensionCodec allowed to register multiple codecs, which are tried one by one until one works. When one works, the index of the list that occupies the codec that works is stored in the encoded payload for later decoding:

## Encoding

[
  MyFirstCodec,  <- tried, but did not work
  MySecondCodec, <- tried, but did not work
  MyThirdCodec, <- tried, and it work, store index 2 in payload
  MyFourthCodec
]

payload { index: 2, data: ... }

## Decoding

payload { index: 2, data: ... }

[
  MyFirstCodec,
  MySecondCodec,
  MyThirdCodec, <- index is 2, just this codec is attempted
  MyFourthCodec
]

The issue with this setup is that codecs can only be added to the end of the list, otherwise, while decoding, the index will be messed up and decoding will fail. In a setup with progressive rollouts this is very likely to happen.

While working in a small team, it's reasonable to expect developers to behave and just add new codecs at the end, however, when there are many teams contributing to the same list, with a non-centralized piece of code that has mutable access to it, it's easy to be in the situation where new codecs are not added at the end.

What changes are included in this PR?

Introduces a new ComposedNamedPhysicalExtensionCodec that identifies encoded payloads by codec name instead of by index in a list. This way, registration order does not matter, and this problem becomes irrepresentable:

## Encoding

{
  "MyFirstCodec": MyFirstCodec,  <- tried, but did not work
  "MySecondCodec": MySecondCodec, <- tried, but did not work
  "MyThirdCodec": MyThirdCodec, <- it worked!
  "MyFourthCodec": MyFourthCodec
}

payload { name: "MyThirdCodec", data: ... }

## Decoding

payload { index: "MyThirdCodec", data: ... }

{
  "MyFourthCodec": MyFourthCodec,
  "MyThirdCodec": MyThirdCodec, <- use this one, no matter the order
  "MyFirstCodec": MyFirstCodec,
  "MySecondCodec": MySecondCodec
}

What is the testing strategy for this PR?

TODO

Are there any user-facing changes?

New ComposedNamedPhysicalExtensionCodec is added to the public API, while keeping the previous ComposedPhysicalExtensionCodec still available.

@github-actions github-actions Bot added the proto Related to proto crate label Aug 31, 2026
@github-actions

Copy link
Copy Markdown

Thank you for opening this pull request!

Reviewer note: cargo-semver-checks reported the current version number is not SemVer-compatible with the changes in this pull request (compared against the base branch).

Details
     Cloning apache/main
    Building datafusion-proto v55.0.0 (current)
       Built [  60.036s] (current)
     Parsing datafusion-proto v55.0.0 (current)
      Parsed [   0.020s] (current)
    Building datafusion-proto v55.0.0 (baseline)
       Built [  58.164s] (baseline)
     Parsing datafusion-proto v55.0.0 (baseline)
      Parsed [   0.020s] (baseline)
    Checking datafusion-proto v55.0.0 -> v55.0.0 (no change; assume patch)
     Checked [   0.127s] 223 checks: 222 pass, 1 fail, 0 warn, 31 skip

--- failure type_marked_deprecated: #[deprecated] added on type ---

Description:
A type is now #[deprecated]. Downstream crates will get a compiler warning when using this type.
        ref: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-deprecated-attribute
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.50.0/src/lints/type_marked_deprecated.ron

Failed in:
  Struct ComposedPhysicalExtensionCodec in /home/runner/work/datafusion/datafusion/datafusion/proto/src/physical_plan/mod.rs:1973

     Summary semver requires new minor version: 0 major and 1 minor checks failed
    Finished [ 120.596s] datafusion-proto

@github-actions github-actions Bot added the auto detected api change Auto detected API change label Aug 31, 2026
Comment on lines +1968 to +1971
#[deprecated(
since = "56.0.0",
note = "Please use `ComposedNamedPhysicalExtensionCodec`"
)]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Still not sure if it's worth to deprecate this one, FWIW both could live together.

Comment on lines +2081 to +2087
/// A PhysicalExtensionCodec that tries one of multiple inner codecs until one works.
/// The name of the codec that successfully encoded an [`ExecutionPlan`] is stored in the
/// encoded payload, and the codec with that exact name will be used for decoding.
#[derive(Default, Debug)]
pub struct ComposedNamedPhysicalExtensionCodec {
codecs: HashMap<Cow<'static, str>, Arc<dyn PhysicalExtensionCodec>>,
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

cc @milenkovicm, do you have any opinions about this?

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.

Could string make encoded message too big? Could you consider u8 keys

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.

Or even u16 or u32, as the keys

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.

If you consider sorted keys, you can implement codec priority as well. I know strings are more flexible than numbers but they won't remove synchronisation between orgs and they can be abused with key size

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 97 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.56%. Comparing base (a274959) to head (d568122).

Files with missing lines Patch % Lines
datafusion/proto/src/physical_plan/mod.rs 0.00% 97 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #24826      +/-   ##
==========================================
- Coverage   81.58%   81.56%   -0.03%     
==========================================
  Files        1123     1123              
  Lines      406610   406707      +97     
  Branches   406610   406707      +97     
==========================================
- Hits       331719   331715       -4     
- Misses      55453    55554     +101     
  Partials    19438    19438              

☔ 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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

Labels

auto detected api change Auto detected API change proto Related to proto crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants