Skip to content

Conversation

@ewanharris
Copy link
Member

@ewanharris ewanharris commented Oct 7, 2025

Description

Adds support for the write conflict options introduced in OpenFGA v1.10.0

Adds onDuplicate and onMissing methods to the ClientWriteOptions/ClientWriteTuplesOptions/ClientDeleteTuplesOptions that can be used to control the behaviour for when a tuple already exists on write (onDuplicate or does not exist on delete (onMissing).

The SDK defaults to sending error for these values (see test updates e.g here) if not provided as that is the default in the API/default behaviour in the server, this is different to the consistency option that has a default value of UNSPECIFIED rather than MINIMIZE_LATENCY to allow differentiating between "not sent by client" vs "set to default value by client".

References

Generated from https://github.com/openfga/sdk-generator/tree/feat/java-write-options using OPEN_API_REF=0ac19aac54f21f3c78970126b84b4c69c6e3b9a2 make build-client-java (and some edits to remove the listStores changes.

Review Checklist

  • I have clicked on "allow edits by maintainers".
  • I have added documentation for new/changed functionality in this PR or in a PR to openfga.dev [Provide a link to any relevant PRs in the references section above]
  • The correct base branch is being used, if not main
  • I have added tests to validate that the change in functionality is working as expected

Summary by CodeRabbit

  • New Features

    • Added optional conflict-handling for write/delete operations: choose behavior for duplicate writes and missing deletes (error or ignore). Supported across single and transactional writes.
  • Documentation

    • Expanded README and API docs with “Conflict options for write operations,” clarifying idempotency, option precedence when mixed, rollback behavior, and multiple usage examples.
  • Tests

    • Added comprehensive tests covering on-duplicate and on-missing options across client and model layers.
  • Chores

    • Updated integration test environment to a newer OpenFGA version for compatibility with the documented features.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 7, 2025

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Adds conflict-handling options for write/delete requests: on_duplicate (writes) and on_missing (deletes). Threads these options through client options to request models, updates docs and Javadocs, adds enums and serialization logic, extends helpers/overloads, and updates tests. Integration tests now use OpenFGA v1.10.2.

Changes

Cohort / File(s) Summary of changes
Docs: conflict options and Write API
README.md, docs/OpenFgaApi.md, docs/WriteRequestWrites.md, docs/WriteRequestDeletes.md
Document on_duplicate/on_missing behavior, precedence, rollback, defaults; add enums and fields in docs; examples updated.
Models: request enums and fields
src/main/java/dev/openfga/sdk/api/model/WriteRequestWrites.java, src/main/java/dev/openfga/sdk/api/model/WriteRequestDeletes.java
Add OnDuplicateEnum/OnMissingEnum; add on_duplicate/on_missing fields with JSON and URL serialization; update equals/hashCode/toString.
Client configuration options
src/main/java/dev/openfga/sdk/api/configuration/ClientWriteOptions.java, .../ClientWriteTuplesOptions.java, .../ClientDeleteTuplesOptions.java
Add fluent getters/setters for onDuplicate/onMissing; expose new fields.
Client plumbing: threading options
src/main/java/dev/openfga/sdk/api/client/OpenFgaClient.java, .../client/model/ClientTupleKey.java, .../client/model/ClientTupleKeyWithoutCondition.java
Pass onDuplicate/onMissing into request builders; add overloads to include options; preserve default behavior when null.
API Javadoc updates
src/main/java/dev/openfga/sdk/api/OpenFgaApi.java
Update method Javadocs to describe idempotency, options, precedence, and rollback; no signature changes.
Integration tests: OpenFGA version bump
src/test-integration/java/dev/openfga/sdk/api/OpenFgaApiIntegrationTest.java, .../client/OpenFgaClientIntegrationTest.java, .../example/ExampleTest.java
Update container image to openfga/openfga:v1.10.2.
Unit tests: API write option coverage
src/test/java/dev/openfga/sdk/api/OpenFgaApiTest.java, .../client/OpenFgaClientHeadersTest.java, .../client/OpenFgaClientTest.java
Add/adjust tests to assert on_duplicate/on_missing in payloads across write/delete paths.
Unit tests: helper/model enums
src/test/java/dev/openfga/sdk/api/client/model/ClientTupleKeyTest.java, .../ClientTupleKeyWithoutConditionTest.java, .../api/model/WriteRequestWritesTest.java, .../api/model/WriteRequestDeletesTest.java
New tests for helper overloads and enum fromValue behavior; verify defaults and explicit settings.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor App
  participant Client as OpenFgaClient
  participant API as OpenFgaApi
  participant Svc as OpenFGA Server

  App->>Client: write(..., options{onDuplicate?, onMissing?})
  Client->>Client: Build WriteRequestWrites/Deletes\n(apply on_duplicate/on_missing if provided)
  Client->>API: write(request)
  API->>Svc: POST /write {writes{..., on_duplicate}, deletes{..., on_missing}}
  alt Success
    Svc-->>API: 200 OK
    API-->>Client: Response
    Client-->>App: Return success
  else Error (conflict/precedence)
    Svc-->>API: 4xx (transaction rolled back)
    API-->>Client: Error
    Client-->>App: Propagate error
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • evansims
  • rhamzeh

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 19.35% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title “feat: add support for write conflict settings” accurately and concisely summarizes the core enhancement of the pull request, namely the addition of onDuplicate and onMissing conflict-handling options for write and delete operations in the SDK. It directly reflects the primary feature change without extraneous details or noise.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov-commenter
Copy link

codecov-commenter commented Oct 7, 2025

Codecov Report

❌ Patch coverage is 73.80952% with 22 lines in your changes missing coverage. Please review.
✅ Project coverage is 36.44%. Comparing base (4c55350) to head (57be69e).

Files with missing lines Patch % Lines
...dev/openfga/sdk/api/model/WriteRequestDeletes.java 59.25% 11 Missing ⚠️
.../dev/openfga/sdk/api/model/WriteRequestWrites.java 59.25% 11 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main     #234      +/-   ##
============================================
+ Coverage     35.97%   36.44%   +0.46%     
- Complexity     1116     1140      +24     
============================================
  Files           187      187              
  Lines          7096     7170      +74     
  Branches        806      822      +16     
============================================
+ Hits           2553     2613      +60     
- Misses         4438     4452      +14     
  Partials        105      105              

☔ 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.

@ewanharris ewanharris force-pushed the feat/write-conflict-options branch from c861b1e to 57be69e Compare October 14, 2025 15:49
@ewanharris ewanharris marked this pull request as ready for review October 14, 2025 15:50
@ewanharris ewanharris requested review from a team as code owners October 14, 2025 15:50
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (12)
docs/WriteRequestDeletes.md (1)

11-21: Fix anchor and minor formatting in docs.

The fragment [#OnMissingEnum] is likely invalid (MD051). GitHub generates “## Enum: OnMissingEnum” as #enum-onmissingenum. Also, prefer plain quotes over HTML entities. Optionally note the default.

Apply:

-|**onMissing** | [**OnMissingEnum**](#OnMissingEnum) | On 'error', the API returns an error when deleting a tuple that does not exist. On 'ignore', deletes of non-existent tuples are treated as no-ops. |  [optional] |
+|**onMissing** | [**OnMissingEnum**](#enum-onmissingenum) | On 'error', the API returns an error when deleting a tuple that does not exist. On 'ignore', deletes of non-existent tuples are treated as no-ops. |  [optional] |

- | ERROR | "error" |
- | IGNORE | "ignore" |
- | UNKNOWN_DEFAULT_OPEN_API | "unknown_default_open_api" |
+ | ERROR | "error" |
+ | IGNORE | "ignore" |
+ | UNKNOWN_DEFAULT_OPEN_API | "unknown_default_open_api" |

Optional:

- |**onMissing** | ... |  [optional] |
+ |**onMissing** | ... |  [optional] (Default: ERROR) |

Based on static analysis hints

src/test/java/dev/openfga/sdk/api/client/model/ClientTupleKeyWithoutConditionTest.java (1)

1-82: Good coverage of onMissing defaulting and explicit values.

Tests read clearly and validate key paths.

Consider a parameterized test to reduce duplication across the three explicit/default cases.

src/test/java/dev/openfga/sdk/api/client/model/ClientTupleKeyTest.java (1)

1-82: OnDuplicate behavior covered well.

Assertions for null/explicit/default are correct.

You can parameterize these scenarios to DRY the setup.

src/test/java/dev/openfga/sdk/api/client/OpenFgaClientTest.java (1)

1598-1639: Strengthen verification in non-transaction conflict-options test.

Currently verifies only total POST count. Mirror earlier tests by asserting one request used writeBody and one used deleteBody (and headers), reducing false positives.

-        // Then
-        mockHttpClient.verify().post(postPath).called(2); // One for writes, one for deletes
+        // Then
+        mockHttpClient
+                .verify()
+                .post(postPath)
+                .withBody(is(writeBody))
+                .withHeader(CLIENT_METHOD_HEADER, "Write")
+                .withHeader(CLIENT_BULK_REQUEST_ID_HEADER, anyValidUUID())
+                .called(1);
+        mockHttpClient
+                .verify()
+                .post(postPath)
+                .withBody(is(deleteBody))
+                .withHeader(CLIENT_METHOD_HEADER, "Write")
+                .withHeader(CLIENT_BULK_REQUEST_ID_HEADER, anyValidUUID())
+                .called(1);
src/main/java/dev/openfga/sdk/api/configuration/ClientWriteTuplesOptions.java (1)

15-39: onDuplicate option wiring looks good; add a short Javadoc about defaults

Minor polish: document that null omits the field (server defaults to "error"). Optionally note that UNKNOWN_DEFAULT_OPEN_API should not be set by callers.

     public ClientWriteTuplesOptions onDuplicate(WriteRequestWrites.OnDuplicateEnum onDuplicate) {
         this.onDuplicate = onDuplicate;
         return this;
     }

+    /**
+     * Controls behavior when writing a tuple that already exists.
+     * If null, the field is omitted (server defaults to "error").
+     */
     public WriteRequestWrites.OnDuplicateEnum getOnDuplicate() {
         return onDuplicate;
     }
src/main/java/dev/openfga/sdk/api/client/model/ClientTupleKey.java (1)

48-60: Guard against sending UNKNOWN_DEFAULT_OPEN_API

Skip setting onDuplicate when it's UNKNOWN_DEFAULT_OPEN_API to avoid emitting an unrecognized value.

-        if (onDuplicate != null) {
-            writes.onDuplicate(onDuplicate);
-        }
+        if (onDuplicate != null
+                && onDuplicate != WriteRequestWrites.OnDuplicateEnum.UNKNOWN_DEFAULT_OPEN_API) {
+            writes.onDuplicate(onDuplicate);
+        }
src/main/java/dev/openfga/sdk/api/client/model/ClientTupleKeyWithoutCondition.java (1)

30-43: Also skip UNKNOWN_DEFAULT_OPEN_API for onMissing

Mirror the writes guard to prevent sending an unknown enum value.

-        if (onMissing != null) {
-            deletes.onMissing(onMissing);
-        }
+        if (onMissing != null
+                && onMissing != WriteRequestDeletes.OnMissingEnum.UNKNOWN_DEFAULT_OPEN_API) {
+            deletes.onMissing(onMissing);
+        }
src/main/java/dev/openfga/sdk/api/configuration/ClientDeleteTuplesOptions.java (1)

15-39: onMissing option is wired correctly; consider brief Javadoc

Note that null omits the field (server defaults to "error"). Helps users choose behavior.

     public ClientDeleteTuplesOptions onMissing(WriteRequestDeletes.OnMissingEnum onMissing) {
         this.onMissing = onMissing;
         return this;
     }

+    /**
+     * Controls behavior when deleting a tuple that does not exist.
+     * If null, the field is omitted (server defaults to "error").
+     */
     public WriteRequestDeletes.OnMissingEnum getOnMissing() {
         return onMissing;
     }
docs/OpenFgaApi.md (1)

2306-2306: Docs read well; minor grammar + clarify defaults

  • Replace “an user” with “a user”.
  • Add sentence: “If omitted, both options default to "error".”
-The Write API will transactionally update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and an user.
+The Write API will transactionally update the tuples for a certain store. Tuples and type definitions allow OpenFGA to determine whether a relationship exists between an object and a user.
+If omitted, both on_duplicate and on_missing default to "error".

Also applies to: 2381-2381

src/test/java/dev/openfga/sdk/api/OpenFgaApiTest.java (1)

1431-1462: Combined conflict options exercised end-to-end

Covers simultaneous on_duplicate/on_missing. Good integration signal.

To cut duplication/noise across similar tests, consider a small helper to build WriteRequest with (writes|deletes) and a parameterized JUnit test over {IGNORE, ERROR}.

src/main/java/dev/openfga/sdk/api/model/WriteRequestDeletes.java (1)

220-228: Prefer using enum getValue() for URL encoding

Minor clarity tweak: avoid relying on toString(); encode the JSON value directly.

Apply:

- URLEncoder.encode(String.valueOf(getOnMissing()), StandardCharsets.UTF_8)
+ URLEncoder.encode(getOnMissing().getValue(), StandardCharsets.UTF_8)
src/main/java/dev/openfga/sdk/api/model/WriteRequestWrites.java (1)

220-228: Prefer using enum getValue() for URL encoding

Mirror the deletes suggestion for consistency/clarity.

Apply:

- URLEncoder.encode(String.valueOf(getOnDuplicate()), StandardCharsets.UTF_8)
+ URLEncoder.encode(getOnDuplicate().getValue(), StandardCharsets.UTF_8)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4c55350 and 57be69e.

📒 Files selected for processing (23)
  • README.md (1 hunks)
  • docs/OpenFgaApi.md (2 hunks)
  • docs/WriteRequestDeletes.md (1 hunks)
  • docs/WriteRequestWrites.md (1 hunks)
  • src/main/java/dev/openfga/sdk/api/OpenFgaApi.java (2 hunks)
  • src/main/java/dev/openfga/sdk/api/client/OpenFgaClient.java (3 hunks)
  • src/main/java/dev/openfga/sdk/api/client/model/ClientTupleKey.java (1 hunks)
  • src/main/java/dev/openfga/sdk/api/client/model/ClientTupleKeyWithoutCondition.java (1 hunks)
  • src/main/java/dev/openfga/sdk/api/configuration/ClientDeleteTuplesOptions.java (2 hunks)
  • src/main/java/dev/openfga/sdk/api/configuration/ClientWriteOptions.java (2 hunks)
  • src/main/java/dev/openfga/sdk/api/configuration/ClientWriteTuplesOptions.java (2 hunks)
  • src/main/java/dev/openfga/sdk/api/model/WriteRequestDeletes.java (5 hunks)
  • src/main/java/dev/openfga/sdk/api/model/WriteRequestWrites.java (5 hunks)
  • src/test-integration/java/dev/openfga/sdk/api/OpenFgaApiIntegrationTest.java (1 hunks)
  • src/test-integration/java/dev/openfga/sdk/api/client/OpenFgaClientIntegrationTest.java (1 hunks)
  • src/test-integration/java/dev/openfga/sdk/example/ExampleTest.java (1 hunks)
  • src/test/java/dev/openfga/sdk/api/OpenFgaApiTest.java (5 hunks)
  • src/test/java/dev/openfga/sdk/api/client/OpenFgaClientHeadersTest.java (2 hunks)
  • src/test/java/dev/openfga/sdk/api/client/OpenFgaClientTest.java (9 hunks)
  • src/test/java/dev/openfga/sdk/api/client/model/ClientTupleKeyTest.java (1 hunks)
  • src/test/java/dev/openfga/sdk/api/client/model/ClientTupleKeyWithoutConditionTest.java (1 hunks)
  • src/test/java/dev/openfga/sdk/api/model/WriteRequestDeletesTest.java (1 hunks)
  • src/test/java/dev/openfga/sdk/api/model/WriteRequestWritesTest.java (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
src/test/java/dev/openfga/sdk/api/client/model/ClientTupleKeyWithoutConditionTest.java (1)
src/main/java/dev/openfga/sdk/api/client/model/ClientTupleKeyWithoutCondition.java (1)
  • ClientTupleKeyWithoutCondition (20-97)
src/main/java/dev/openfga/sdk/api/model/WriteRequestDeletes.java (1)
src/main/java/dev/openfga/sdk/api/model/WriteRequestWrites.java (1)
  • JsonPropertyOrder (30-232)
src/test/java/dev/openfga/sdk/api/client/model/ClientTupleKeyTest.java (1)
src/main/java/dev/openfga/sdk/api/client/model/ClientTupleKey.java (1)
  • ClientTupleKey (21-81)
src/main/java/dev/openfga/sdk/api/client/OpenFgaClient.java (2)
src/main/java/dev/openfga/sdk/api/client/model/ClientTupleKey.java (1)
  • ClientTupleKey (21-81)
src/main/java/dev/openfga/sdk/api/client/model/ClientTupleKeyWithoutCondition.java (1)
  • ClientTupleKeyWithoutCondition (20-97)
src/main/java/dev/openfga/sdk/api/model/WriteRequestWrites.java (1)
src/main/java/dev/openfga/sdk/api/model/WriteRequestDeletes.java (1)
  • JsonPropertyOrder (30-232)
🪛 LanguageTool
docs/WriteRequestDeletes.md

[grammar] ~17-~17: There might be a mistake here.
Context: ...## Enum: OnMissingEnum | Name | Value | |---- | -----| | ERROR | "error&quo...

(QB_NEW_EN)


[grammar] ~18-~18: There might be a mistake here.
Context: ...ingEnum | Name | Value | |---- | -----| | ERROR | "error" | | IGNORE |...

(QB_NEW_EN)


[grammar] ~19-~19: There might be a mistake here.
Context: ...- | -----| | ERROR | "error" | | IGNORE | "ignore" | | UNKNOW...

(QB_NEW_EN)


[grammar] ~20-~20: There might be a mistake here.
Context: ..." | | IGNORE | "ignore" | | UNKNOWN_DEFAULT_OPEN_API | "unkno...

(QB_NEW_EN)

docs/WriteRequestWrites.md

[grammar] ~17-~17: There might be a mistake here.
Context: ... Enum: OnDuplicateEnum | Name | Value | |---- | -----| | ERROR | "error&quo...

(QB_NEW_EN)


[grammar] ~18-~18: There might be a mistake here.
Context: ...ateEnum | Name | Value | |---- | -----| | ERROR | "error" | | IGNORE |...

(QB_NEW_EN)


[grammar] ~19-~19: There might be a mistake here.
Context: ...- | -----| | ERROR | "error" | | IGNORE | "ignore" | | UNKNOW...

(QB_NEW_EN)


[grammar] ~20-~20: There might be a mistake here.
Context: ..." | | IGNORE | "ignore" | | UNKNOWN_DEFAULT_OPEN_API | "unkno...

(QB_NEW_EN)

🪛 markdownlint-cli2 (0.18.1)
docs/WriteRequestDeletes.md

11-11: Link fragments should be valid

(MD051, link-fragments)

docs/WriteRequestWrites.md

11-11: Link fragments should be valid

(MD051, link-fragments)

🔇 Additional comments (26)
src/test-integration/java/dev/openfga/sdk/example/ExampleTest.java (1)

11-11: LGTM! Container version updated to support new conflict options.

The container version update to v1.10.2 aligns with the PR's requirement to support the write conflict options introduced in OpenFGA v1.10.0.

src/main/java/dev/openfga/sdk/api/configuration/ClientWriteOptions.java (2)

15-16: LGTM! Imports added for new conflict handling enums.


24-25: LGTM! Conflict options added with proper fluent API pattern.

The onDuplicate and onMissing fields with their corresponding fluent setters and getters follow the existing patterns in this class. The fields default to null, which allows the SDK to omit these options when not explicitly set, letting the server apply its defaults.

Also applies to: 64-80

docs/WriteRequestWrites.md (2)

11-11: Verify the enum anchor link.

The OnDuplicateEnum reference on this line should link to the enum section below (line 15). Ensure the anchor link works correctly in the rendered documentation.

Based on static analysis hints.


11-21: LGTM! Clear documentation for the new onDuplicate property.

The documentation clearly explains:

  • The optional nature of the property
  • The behavior for each enum value (error vs. ignore)
  • The available enum values including the fallback (UNKNOWN_DEFAULT_OPEN_API)
src/main/java/dev/openfga/sdk/api/OpenFgaApi.java (1)

909-909: LGTM! Comprehensive documentation for write conflict handling.

The updated Javadoc provides clear guidance on:

  • Default non-idempotent behavior
  • How to enable idempotency with on_duplicate: "ignore" and on_missing: "ignore"
  • Precedence rules when mixing ignore and error operations
  • Transaction rollback behavior on failures

The examples clearly demonstrate the usage patterns.

Also applies to: 922-922

README.md (2)

644-657: LGTM! Clear introduction to conflict handling options.

The documentation effectively explains:

  • The purpose of each option (onDuplicate for writes, onMissing for deletes)
  • Version requirement (OpenFGA v1.10.0+)
  • Available enum values with their behavior
  • Default behavior (ERROR)

658-712: LGTM! Comprehensive usage examples for all write methods.

The three examples demonstrate conflict handling with:

  1. write() method - showing both onDuplicate and onMissing together
  2. writeTuples() convenience method - showing onDuplicate
  3. deleteTuples() convenience method - showing onMissing

The code examples follow proper Java syntax and fluent builder patterns.

src/test/java/dev/openfga/sdk/api/model/WriteRequestDeletesTest.java (1)

1-36: LGTM! Comprehensive unit tests for OnMissingEnum.

The test suite provides good coverage:

  • Valid enum values map correctly (ERROR, IGNORE)
  • Unknown values safely fall back to UNKNOWN_DEFAULT_OPEN_API
  • Null input is handled gracefully

The test structure follows JUnit 5 best practices with descriptive test names and clear assertions.

src/test/java/dev/openfga/sdk/api/client/OpenFgaClientHeadersTest.java (2)

402-403: Write payload now asserts default on_duplicate — LGTM.

Matches the new default behavior. Consider updating writeNonTransaction_withHeaders in this file to also include "on_duplicate":"error" for consistency with non‑transaction tests elsewhere.

Example patch to align that test’s expectedBody:

-        String expectedBody = String.format(
-                "{\"writes\":{\"tuple_keys\":[{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\",\"condition\":null}]},\"deletes\":null,\"authorization_model_id\":\"%s\"}",
-                DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT, DEFAULT_AUTH_MODEL_ID);
+        String expectedBody = String.format(
+                "{\"writes\":{\"tuple_keys\":[{\"user\":\"%s\",\"relation\":\"%s\",\"object\":\"%s\",\"condition\":null}],\"on_duplicate\":\"error\"},\"deletes\":null,\"authorization_model_id\":\"%s\"}",
+                DEFAULT_USER, DEFAULT_RELATION, DEFAULT_OBJECT, DEFAULT_AUTH_MODEL_ID);

908-909: Multiple overrides test updated for on_duplicate — LGTM.

Expectation reflects default on_duplicate in writes.

src/test/java/dev/openfga/sdk/api/client/OpenFgaClientTest.java (1)

1146-1147: Assertion updates for conflict options — LGTM.

Expected payloads consistently include on_duplicate/on_missing defaults and option-driven overrides across transaction and non-transaction paths.

Also applies to: 1178-1179, 1207-1212, 1216-1221, 1357-1365, 1397-1405, 1436-1438, 1459-1461, 1475-1496, 1498-1519, 1521-1549, 1550-1573, 1575-1596

src/main/java/dev/openfga/sdk/api/client/OpenFgaClient.java (1)

487-495: All onDuplicate/onMissing variants are covered and call sites verified

Tests validate null/default, IGNORE, and ERROR for both writes and deletes; no further changes needed.

src/test/java/dev/openfga/sdk/api/model/WriteRequestWritesTest.java (1)

1-36: Remove redundant test suggestions; these tests already exist
WriteRequestDeletesTest.java covers OnMissingEnum.fromValue cases, and ClientTupleKeyTest.java/ClientTupleKeyWithoutConditionTest.java include asWriteRequestWrites and asWriteRequestDeletes builder tests.

Likely an incorrect or invalid review comment.

src/test/java/dev/openfga/sdk/api/OpenFgaApiTest.java (8)

1101-1101: Good: default on_duplicate asserted in writes payload

Asserting explicit "on_duplicate":"error" matches the new default in WriteRequestWrites.


1127-1127: Good: default on_missing asserted in deletes payload

Explicit "on_missing":"error" aligns with WriteRequestDeletes default.


1150-1151: Writes + condition context still include on_duplicate default

Confirms serialization with conditions and default conflict option. Looks correct.


1182-1184: Modeled context serialization + on_duplicate default verified

Covers complex context shape and default "error". Solid.


1323-1349: onDuplicate=IGNORE test is precise

Payload and builder usage (WriteRequestWrites.OnDuplicateEnum.IGNORE) are correct.


1350-1376: onDuplicate=ERROR test matches default behavior

Explicit ERROR path validated; mirrors ignore test.


1377-1403: onMissing=IGNORE test is precise

Delete-path conflict option wired and asserted correctly.


1404-1429: onMissing=ERROR test matches default behavior

Explicit ERROR path validated for deletes.

src/main/java/dev/openfga/sdk/api/model/WriteRequestDeletes.java (2)

35-74: Enum with UNKNOWN fallback is appropriate

OnMissingEnum with @JsonCreator/@jsonvalue and UNKNOWN_DEFAULT_OPEN_API safeguards deserialization.


107-127: onMissing field + JSON wiring look correct

Default ERROR, property order, getters/setters, equals/hashCode updates are consistent with writes.

src/main/java/dev/openfga/sdk/api/model/WriteRequestWrites.java (2)

35-74: Enum with UNKNOWN fallback is appropriate

OnDuplicateEnum with @JsonCreator/@jsonvalue and UNKNOWN_DEFAULT_OPEN_API ensures forward-compatible parsing.


107-127: onDuplicate field + JSON wiring look correct

Default ERROR, property order, getters/setters, equals/hashCode updates align with expectations.

@jimmyjames
Copy link
Contributor

The SDK defaults to sending error for these values (see test updates e.g here) if not provided as that is the default in the API/default behaviour in the server, this is different to the consistency option that has a default value of UNSPECIFIED rather than MINIMIZE_LATENCY to allow differentiating between "not sent by client" vs "set to default value by client".

In openfga/sdk-generator#610 it states

If the user does not set the default, the SDK should not send it, relying on the server to implement its default behaviour.

Any reason we can't do that here?

@ewanharris
Copy link
Member Author

I think with some edits to the underlying template we could, but it would impact other properties as the code is how the existing enums are rendered today, it's just that consistency for example explicitly has 3 enum states, "not set", minimize latency, and higher consistency whereas these properties only define the two values and no "not set" state.

The OpenAPI spec declares the properties to have error as the default value (1, 2) , which triggers line 90 in this enum rendering. We would have to change the template to not set the default if the property is marked optional I think, which I guess must be what the existing templates do and Java differed for some reason?

@jimmyjames
Copy link
Contributor

I think with some edits to the underlying template we could, but it would impact other properties as the code is how the existing enums are rendered today, it's just that consistency for example explicitly has 3 enum states, "not set", minimize latency, and higher consistency whereas these properties only define the two values and no "not set" state.

The OpenAPI spec declares the properties to have error as the default value (1, 2) , which triggers line 90 in this enum rendering. We would have to change the template to not set the default if the property is marked optional I think, which I guess must be what the existing templates do and Java differed for some reason?

Yes it does seem we have some inconsistency in the API between consistency "unset" value and here... @rhamzeh do you have any insight into if/why the Java SDK handles optional params differently than other SDKs?

In general I think if params are optional in the API and not specified by the SDK consumer, we shouldn't send them, but obviously should avoid or at least be intentional about introducing any breaking changes to do so.

@rhamzeh
Copy link
Member

rhamzeh commented Oct 14, 2025

If the user does not set the default, the SDK should not send it, relying on the server to implement its default behaviour.

This is another example of me putting things in the issue which are not correct (I had assumed that it was implemented the same as consistency, but here it's different as Ewan mentioned) - in this case the SDKs can match the API as the API does state that error is the default - any change on that would be a breaking change on the API and the SDK.

So to match that the SDKs send error as the default (as that's what the API definition states).

I think we should modify the original issue to remove that statement.

@jimmyjames the Java SDK isn't being inconsistent with the other SDKs here - they'll all have the same behaviour (I think) - the default defined by the API spec will get set

(Just FYI coderabbit called that out on the Go SDK too, and I had resolved it as working as intended. If we decide something different here - let's go back and update that too.)

@jimmyjames
Copy link
Contributor

Thanks for clarifying @rhamzeh! I missed the actual go implementation piece (when I asked copilot about the go SDK implementation, it must have taken the shortcut and just looked up the issue description, and not the actual code ;))

I think we should modify the original issue to remove that statement.

I updated the issue to specify that the default value should be set if not specified by the user.

jimmyjames
jimmyjames previously approved these changes Oct 14, 2025
Copy link
Contributor

@jimmyjames jimmyjames left a comment

Choose a reason for hiding this comment

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

Looks good! Feel free to remove tests that aren't valuable as noted, can re-approve then as needed

@ewanharris ewanharris added this pull request to the merge queue Oct 15, 2025
Merged via the queue into main with commit e45fc26 Oct 15, 2025
40 checks passed
@ewanharris ewanharris deleted the feat/write-conflict-options branch October 15, 2025 16:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Add SDK support for ignoring errors on duplicate writes or missing deletes

4 participants