Skip to content

Core: Add idempotency-key-lifetime to ConfigResponse - #14649

Merged
singhpk234 merged 7 commits into
apache:mainfrom
huaxingao:idempotency_1
Nov 25, 2025
Merged

Core: Add idempotency-key-lifetime to ConfigResponse#14649
singhpk234 merged 7 commits into
apache:mainfrom
huaxingao:idempotency_1

Conversation

@huaxingao

Copy link
Copy Markdown
Contributor

OpenAPI defines idempotency-key-lifetime in CatalogConfig. This PR surfaces that field in the Java model and JSON parser/serializer so capability can be discovered. No client/server behavior changes in this PR.

Follow-ups (separate PRs)

  • Client utilities (UUIDv7, constants).
  • Client opt-in wiring in RESTSessionCatalog and mutation calls.
  • E2E tests with test server idempotency layer.

@huaxingao

Copy link
Copy Markdown
ContributorAuthor

also cc @nastra@flyrain@stevenzwu

}

/** Sets the optional idempotency key lifetime advertised by the server. */
public Builder withIdempotencyKeyLifetime(@Nullable String lifetime) {

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.

I don't think we typically add @Nullable to method params

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Removed. Thanks

Duration.parse(lifetime);
builder.withIdempotencyKeyLifetime(lifetime);
} catch (RuntimeException e) {
// ignore invalid value

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.

I don't think we should ignore this if the lifetime is an invalid value. Also I would add the parsing to JsonUtil to have getDurationStringOrNull(similar to getStringOrNull). That method would throw if the lifetime string can't be parsed to a string and would throw a Cannot parse to a duration string value: ...

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed the code to throw exception.

+ " \"overrides\" : { },\n"
+ " \"idempotency-key-lifetime\" : \"not-a-duration\"\n"
+ "}");
// invalid value is treated as "not advertised"

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.

I believe an invalid value should always throw, similar to how e.g. an invalid value for a number throws

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed. Thanks

Comment threadcore/src/main/java/org/apache/iceberg/util/JsonUtil.java
java.time.Duration.parse(value);
} catch (RuntimeException e) {
throw new IllegalArgumentException(
String.format("Cannot parse to a duration string value: %s: %s", property, value), e);

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.

Suggested change
String.format("Cannot parse to a duration string value: %s: %s", property, value), e);
String.format("Cannot parse to a duration string value: %s: %s", property, node.get(property), e);

for consistency with other JsonUtil methods we should probably add the actual JSON node into the error msg

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Done! Thanks!

JsonUtil.getDurationStringOrNull(
"x", JsonUtil.mapper().readTree("{\"x\": \"30M\"}")))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("x: 30M");

@nastranastraNov 25, 2025

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.

Suggested change
.hasMessageContaining("x: 30M");
.hasMessage("Cannot parse to a duration string value: x: \"30M\"");

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.

I believe it's better to verify the exact error msg as we do in other tests in order to make sure that the error msg has the right format/wording

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Done

() ->
JsonUtil.getDurationStringOrNull("x", JsonUtil.mapper().readTree("{\"x\": \"\"}")))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("x: ");

@nastranastraNov 25, 2025

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.

Suggested change
.hasMessageContaining("x: ");
.hasMessage("Cannot parse to a duration string value: x: \"\"");

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Done. Thanks!

+ " \"idempotency-key-lifetime\" : \"not-a-duration\"\n"
+ "}"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("idempotency-key-lifetime: not-a-duration");

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.

Suggested change
.hasMessageContaining("idempotency-key-lifetime: not-a-duration");
.hasMessage(
"Cannot parse to a duration string value: idempotency-key-lifetime: \"not-a-duration\"");

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed. Thanks

+ " \"idempotency-key-lifetime\" : \"\"\n"
+ "}"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("idempotency-key-lifetime: ");

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.

Suggested change
.hasMessageContaining("idempotency-key-lifetime: ");
.hasMessage("Cannot parse to a duration string value: idempotency-key-lifetime: \"\"");

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed


if (json.hasNonNull(IDEMPOTENCY_KEY_LIFETIME)) {
String lifetime = JsonUtil.getDurationStringOrNull(IDEMPOTENCY_KEY_LIFETIME, json);
if (lifetime != null) {

@nastranastraNov 25, 2025

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.

I don't think we need the additional null check here, since the Builder can just pass through what was set, so this could be simplified/inlined to builder.withIdempotencyKeyLifetime(JsonUtil.getDurationStringOrNull(IDEMPOTENCY_KEY_LIFETIME, json));

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed. Thanks!

@nastranastra changed the title Surface idempotency-key-lifetime in ConfigResponseCore: Add idempotency-key-lifetime to ConfigResponseNov 25, 2025

@nastranastra 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.

LGTM, thanks @huaxingao

@singhpk234singhpk234 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.

LGTM too, thanks @huaxingao !

@singhpk234
singhpk234 merged commit 6a54bc1 into apache:mainNov 25, 2025
44 checks passed
@singhpk234

Copy link
Copy Markdown
Contributor

Thanks @huaxingao for the change and @nastra for the review !

@huaxingao

Copy link
Copy Markdown
ContributorAuthor

Thanks a lot @singhpk234@nastra

@huaxingao
huaxingao deleted the idempotency_1 branch November 25, 2025 23:02
thomaschow pushed a commit to thomaschow/iceberg that referenced this pull request Jan 19, 2026
talatuyarer pushed a commit to talatuyarer/iceberg that referenced this pull request Apr 1, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@huaxingao@singhpk234@nastra