Skip to content

Conversation

@samansmink
Copy link
Collaborator

@samansmink samansmink commented Aug 21, 2025

What changes are proposed in this pull request?

This PR adds ffi functions for Transaction::with_transaction_id and Snapshot::get_app_id_version. With these primitives, idempotent writes can be achieved.

Because we were lacking an FFI safe Option implementation, I added a FFI safe OptionalValue struct. Note that this doesn't really result in the nicest looking C API, but it does work and is clean from the rust side.

This PR affects the following public APIs

added to ffi:

  • get_app_id_version(snapshot, app_id, engine)
  • with_transaction_id(txn, app_id, version, engine)

change function call:

  • get_transform_for_row now returns new FFI-safe OptionalValue instead of Option

How was this change tested?

a new test was added that was based on the test_write_txn_actions test from kernel crate

Notes to reviewer

PTAL at the OptionalValue<T> struct added as an FFI safe Option<T>

@github-actions github-actions bot added the breaking-change Change that require a major version bump label Aug 21, 2025
@samansmink samansmink changed the title feat: add ffi for idempotent write primitives feat!: add ffi for idempotent write primitives Aug 25, 2025
@codecov
Copy link

codecov bot commented Aug 26, 2025

Codecov Report

❌ Patch coverage is 92.64706% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.73%. Comparing base (d555b76) to head (d5458b6).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
ffi/src/transaction/transaction_id.rs 93.79% 0 Missing and 8 partials ⚠️
ffi/src/scan.rs 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1191      +/-   ##
==========================================
+ Coverage   84.68%   84.73%   +0.04%     
==========================================
  Files         116      117       +1     
  Lines       29762    29894     +132     
  Branches    29762    29894     +132     
==========================================
+ Hits        25204    25330     +126     
+ Misses       3342     3340       -2     
- Partials     1216     1224       +8     

☔ View full report in Codecov by Sentry.
📢 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.

Copy link
Member

@zachschuermann zachschuermann left a comment

Choose a reason for hiding this comment

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

thanks @samansmink! few comments/questions!

row: usize,
transforms: &CTransforms,
) -> Option<Handle<SharedExpression>> {
) -> OptionalValue<Handle<SharedExpression>> {
Copy link
Member

Choose a reason for hiding this comment

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

changed function signature but not test change points to missing coverage? perhaps let's track an issue to fix?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

will do!

version: i64,
) -> DeltaResult<Handle<ExclusiveTransaction>> {
let app_id_string: DeltaResult<String> = unsafe { TryFromStringSlice::try_from_slice(&app_id) };
Ok(Box::new(txn.with_transaction_id(app_id_string?, version)).into())
Copy link
Member

Choose a reason for hiding this comment

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

one thing i'm noticing with these builder FFIs - we are un-boxing (above) and re-boxing (here) every builder method that consumes self. maybe not worth optimizing yet but seems non-ideal

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This sounds like it would be a follow up issue to this PR, right? Should we open an issue for it?

Comment on lines 62 to 68
fn get_app_id_version_impl(
snapshot: Arc<Snapshot>,
app_id: DeltaResult<String>,
extern_engine: &dyn ExternEngine,
) -> DeltaResult<Option<i64>> {
snapshot.get_app_id_version(&app_id?, extern_engine.engine().as_ref())
}
Copy link
Member

Choose a reason for hiding this comment

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

do we need this or could we just inline snapshot.get_app_id_version(...) above?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

well the app_id might be a DeltaResult::Err right? so then we'd need to handle that anyway so I thought this was simpler and more in line with the other ffi methods?

Perhaps my rust skills are lacking here, but how else would we cleanly return an ExternResult::Err from get_app_id_version if app_id is a DeltaResult::Err?

Copy link
Collaborator

Choose a reason for hiding this comment

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

makes sense that it's easier to return the error 👍

@zachschuermann
Copy link
Member

hey @samansmink just ping whenever you're ready for us to take another look!

@samansmink
Copy link
Collaborator Author

@zachschuermann I think CI should pass now, I still need to look at how to more cleanly fix the miri issue with the test. I've disabled miri for the whole test for now.

There's only your comment about get_app_id_version still open for discussion, I think the rest if fixed now! Would you take another look?

@OussamaSaoudi
Copy link
Collaborator

@samansmink looks good, just needs a rebase and some clearer naming :)

@samansmink
Copy link
Collaborator Author

Thanks for the review @OussamaSaoudi! Applied proposed fixes and updated the branch!

@nicklan nicklan removed request for nicklan and scovich October 14, 2025 23:11
@samansmink samansmink force-pushed the poc-idempotent-writes branch from dfe0197 to 63ef6e6 Compare October 19, 2025 18:42
Copy link
Member

@zachschuermann zachschuermann left a comment

Choose a reason for hiding this comment

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

LGTM thanks @samansmink!

@samansmink
Copy link
Collaborator Author

@zachschuermann done!

@zachschuermann zachschuermann merged commit 189c24e into delta-io:main Oct 22, 2025
22 checks passed
@djouallah
Copy link

@samansmink does this means CREATE TABLE is supported too ?

@samansmink
Copy link
Collaborator Author

@djouallah no, not yet unfortunately!

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

Labels

breaking-change Change that require a major version bump

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants