Skip to content

Conversation

@huaxingao
Copy link
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.

@github-actions github-actions bot added the core label Nov 21, 2025
@huaxingao
Copy link
Contributor Author

also cc @nastra @flyrain @stevenzwu

}

/** Sets the optional idempotency key lifetime advertised by the server. */
public Builder withIdempotencyKeyLifetime(@Nullable String lifetime) {
Copy link
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
Contributor Author

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
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
Contributor Author

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
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
Contributor Author

Choose a reason for hiding this comment

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

Fixed. Thanks

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
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
Contributor Author

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");
Copy link
Contributor

@nastra nastra Nov 25, 2025

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
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
Contributor Author

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: ");
Copy link
Contributor

@nastra nastra Nov 25, 2025

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
Contributor Author

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
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
Contributor Author

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
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
Contributor Author

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) {
Copy link
Contributor

@nastra nastra Nov 25, 2025

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
Contributor Author

Choose a reason for hiding this comment

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

Fixed. Thanks!

@nastra nastra changed the title Surface idempotency-key-lifetime in ConfigResponse Core: Add idempotency-key-lifetime to ConfigResponse Nov 25, 2025
Copy link
Contributor

@nastra nastra 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 @huaxingao

Copy link
Contributor

@singhpk234 singhpk234 left a comment

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:main Nov 25, 2025
44 checks passed
@singhpk234
Copy link
Contributor

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

@huaxingao
Copy link
Contributor Author

Thanks a lot @singhpk234 @nastra

Sign up for free to 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