Skip to content

Conversation

@yingjianwu98
Copy link
Contributor

@yingjianwu98 yingjianwu98 commented Aug 26, 2025

As we transition to using WAP with branches, we’ve noticed a gap in debugging observability compared to the previous approach using wap.id. Specifically, it’s difficult to determine which snapshots were created by WAP branches.

This PR addresses the issue by setting snapshot properties on snapshots that are created by WAP branches, making it easier to trace their origin and improve overall observability.

add snapshot properties for wap created snapshots
Comment on lines 94 to 99
assertThat(
table
.snapshot(table.refs().get(BRANCH).snapshotId())
.summary()
.get(SnapshotSummary.WAP_BRANCH_PROP))
.isEqualTo(BRANCH);
Copy link
Contributor

Choose a reason for hiding this comment

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

We should use AbstractMapAssert's methods for better failure messages:

              assertThat(table.snapshot(table.refs().get(BRANCH).snapshotId()).summary())
                  .containsEntry(SnapshotSummary.WAP_BRANCH_PROP, BRANCH);

Comment on lines 35 to 40
assertThat(
table
.snapshot(table.refs().get("main").snapshotId())
.summary()
.get(SnapshotSummary.WAP_BRANCH_PROP))
.isNull();
Copy link
Contributor

@ebyhr ebyhr Aug 27, 2025

Choose a reason for hiding this comment

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

We should use AbstractMapAssert's methods for better failure messages:

              assertThat(table.snapshot(table.refs().get("main").snapshotId()).summary())
                  .doesNotContainKey(SnapshotSummary.WAP_BRANCH_PROP);

public static final String REPLACED_MANIFESTS_COUNT = "manifests-replaced";
public static final String KEPT_MANIFESTS_COUNT = "manifests-kept";
public static final String PROCESSED_MANIFEST_ENTRY_COUNT = "entries-processed";
public static final String WAP_BRANCH_PROP = "wap.branch";
Copy link
Contributor

Choose a reason for hiding this comment

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

How about moving this constant under STAGED_WAP_ID_PROP?

@yingjianwu98 yingjianwu98 changed the title add snapshot properties for snapshot created by wap branches Core, Spark: add snapshot properties for snapshot created by wap branches Aug 27, 2025
@yingjianwu98
Copy link
Contributor Author

Thanks for the comments @ebyhr @huaxingao

I have addressed them and let me know what you think!

Comment on lines 31 to 38
assertThatCode(
() -> {
sql("INSERT INTO %s VALUES (4, 'd')", tableName);
Table table = validationCatalog.loadTable(tableIdent);
assertThat(table.snapshot(table.refs().get("main").snapshotId()).summary())
.doesNotContainKey(SnapshotSummary.WAP_BRANCH_PROP);
})
.doesNotThrowAnyException();
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need the outer assertThatCode()...doesNotThrowAnyException() method?
Same for TestPartitionedWritesToWapBranch.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah, not really needed. Remove the outer assertion.

@huaxingao
Copy link
Contributor

@yingjianwu98 Could you add coverage for the SparkPositionDeltaWrite code path?

@huaxingao
Copy link
Contributor

@RussellSpitzer Could you please take a look at this PR too when you have a moment? Thanks!

if (wapEnabled) {
if (wapId != null) {
operation.set(SnapshotSummary.STAGED_WAP_ID_PROP, wapId);
operation.stageOnly();
Copy link
Member

Choose a reason for hiding this comment

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

Setting this to stageOnly sounds like it's outside the concept of setting properties to me

.parse();
}

private String getWapBranch() {
Copy link
Member

Choose a reason for hiding this comment

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

nit: We don't use get in our methods for getters

// write-audit-publish is enabled for this table and job
// stage the changes without changing the current snapshot
operation.set(SnapshotSummary.STAGED_WAP_ID_PROP, wapId);
operation.stageOnly();
Copy link
Member

Choose a reason for hiding this comment

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

I mentioned this above, but i'm not comfortable extracting stageOnly here. That seems a bit different than "setWapProperties". Perhaps a rename may make this a bit more clear, but currently it feels like we are hiding an important state change on operation.

@RussellSpitzer
Copy link
Member

I think my big comment here is I have no problem with introducing the wap.branch property, but I don't think we should couple the "staging" logic in the function which sets that property. I think if we isolate the change to just setting either wap.id or branch, we are all set.

-- Note we may also add to the Spec index
https://github.com/apache/iceberg/blob/main/format/spec.md#other-fields

boolean wapEnabled,
String wapId,
String branch,
Predicate<String> isWapBranch) {
Copy link
Member

Choose a reason for hiding this comment

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

Why do we need a functional interface here?

Copy link
Contributor Author

@yingjianwu98 yingjianwu98 Sep 2, 2025

Choose a reason for hiding this comment

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

I initially want to pass the SparkWriteConf but it will introduce an extra spark dependency in the util module.

Copy link
Member

Choose a reason for hiding this comment

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

Hmmm let's try to think of an alternative here? Maybe we just only pass through "branch" if it is a Wap branch?

So have wapId and wapBranch as parameters

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure sounds good, and I also agree to separate out the stageOnly commit into a separate function. And the function only responsibility will just be setting the snapshot properties.

return confParser.stringConf().sessionConf(SparkSQLProperties.WAP_BRANCH).parseOptional();
}

public boolean isWapBranch(String branchName) {
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure why we need this method? Aren't we just always returning true of the wapBranch is not null and matches the branch being written too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ah, I am thinking just wap branches will have this snapshot properties but for other branches, we won't set the property.

@yingjianwu98
Copy link
Contributor Author

Thanks everyone for the review again.

I have updated the PR based on suggestions and refactor the code.
I have also added some more tests but not sure if this is the best place to add these tests.

@github-actions
Copy link

github-actions bot commented Oct 7, 2025

This pull request has been marked as stale due to 30 days of inactivity. It will be closed in 1 week if no further activity occurs. If you think that’s incorrect or this pull request requires a review, please simply write any comment. If closed, you can revive the PR at any time and @mention a reviewer or discuss it on the [email protected] list. Thank you for your contributions.

@github-actions github-actions bot added the stale label Oct 7, 2025
@github-actions
Copy link

This pull request has been closed due to lack of activity. This is not a judgement on the merit of the PR in any way. It is just a way of keeping the PR queue manageable. If you think that is incorrect, or the pull request requires review, you can revive the PR at any time.

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.

4 participants