Skip to content

feat(go): add support for write conflict writes#611

Merged
rhamzeh merged 8 commits into
mainfrom
feat/go-idempotent-writes
Oct 8, 2025
Merged

feat(go): add support for write conflict writes#611
rhamzeh merged 8 commits into
mainfrom
feat/go-idempotent-writes

Conversation

@rhamzeh

@rhamzeh rhamzeh commented Sep 12, 2025

Copy link
Copy Markdown
Member

Description

Note: This requires generation using the following API Ref: openfga/api@0ac19aa

OPEN_API_REF=0ac19aac54f21f3c78970126b84b4c69c6e3b9a2 make test-client-go

What problem is being solved?

How is it being solved?

What changes are made to solve it?

References

addresses the go part of #610
generates openfga/go-sdk#230

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

    • Go client: Added per-call conflict options for Write operations to control behavior on duplicate writes and deleting missing tuples (defaults to “error”). Requires OpenFGA v1.10.0+.
  • Documentation

    • Expanded Go client README with usage examples for conflict options.
    • Changelog updated to note conflict options.
  • Tests

    • Added comprehensive tests covering conflict handling in writes/deletes and request JSON behavior.
    • Expanded client tests using templated aliases.
  • Chores

    • Updated CI configuration.
    • Added generation overrides and supporting test templates for the Go client.

@coderabbitai

coderabbitai Bot commented Sep 12, 2025

Copy link
Copy Markdown
Contributor

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 Go client writes/deletes in templates, updates example and README template, expands tests (client, API, models), updates Go client config overrides to include models tests, and sets an OPEN_API_REF env in CI. Changelog documents the feature.

Changes

Cohort / File(s) Summary
Go client write conflict options
config/clients/go/template/client/client.mustache
Introduces ClientWriteConflictOptions, enums for writes/deletes conflict modes, extends ClientWriteOptions with Conflict, and propagates OnDuplicate/OnMissing in Write requests including chunked writes.
Go client tests
config/clients/go/template/api_test.mustache, config/clients/go/template/client/client_test.mustache, config/clients/go/template/models_test.mustache, config/clients/go/config.overrides.json
Adds unit tests for write/delete conflict handling and request payloads; converts tests to templated package aliases; adds models tests template and maps it in config overrides.
Docs and examples
config/clients/go/template/README_calling_api.mustache, config/clients/go/template/example/example1/example1.go, config/clients/go/CHANGELOG.md.mustache
Documents conflict options in README (duplicated section), updates example to set WritesOnDuplicate=ignore, and updates changelog Unreleased notes.
CI workflow
.github/workflows/main.yaml
Adds OPEN_API_REF env var to Go SDK tests step.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant App as Application
  participant Client as Go SDK Client
  participant API as OpenFGA API

  App->>Client: Write(tuple writes/deletes, options{Conflict})
  note right of Client: If request > chunk size, split into sub-requests

  alt Non-chunked
    Client->>API: POST /stores/{storeId}/write<br/>body: {writes{on_duplicate}, deletes{on_missing}}
    API-->>Client: WriteResponse
  else Chunked
    loop For each chunk
      Client->>API: POST /write with same Conflict options
      API-->>Client: Partial response
    end
  end

  Client-->>App: Final WriteResponse
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Suggested reviewers

  • ewanharris

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "feat(go): add support for write conflict writes" accurately identifies the primary change: adding conflict-handling support for write operations in the Go client (new Conflict option types, template and client updates, and accompanying tests), which matches the PR summary and file diffs.

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.

@rhamzeh
rhamzeh force-pushed the feat/go-idempotent-writes branch from cb76c77 to 76cde48 Compare September 12, 2025 23:37
@rhamzeh
rhamzeh force-pushed the feat/go-idempotent-writes branch from 76cde48 to 7efdc40 Compare September 12, 2025 23:49
@rhamzeh rhamzeh changed the title feat(go): add support for idempotent writes feat(go): add support for write conflict writes Sep 12, 2025
@rhamzeh
rhamzeh marked this pull request as ready for review September 12, 2025 23:54
@rhamzeh
rhamzeh requested a review from a team as a code owner September 12, 2025 23:54
@rhamzeh rhamzeh mentioned this pull request Sep 12, 2025
4 tasks

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (9)
config/clients/go/template/client/client.mustache (2)

1587-1593: Guard against nil body in WriteExecute.

Calling Execute without Body will panic on len(request.GetBody().Writes).

Apply:

 func (client *{{appShortName}}Client) WriteExecute(request SdkClientWriteRequestInterface) (*ClientWriteResponse, error) {
+  if request.GetBody() == nil {
+    return nil, FgaRequiredParamError{param: "body"}
+  }
   options := request.GetOptions()

1728-1731: Bug: delete chunk end uses writeChunkSize.

This will overshoot or undershoot delete chunking.

Apply:

-            end := int(math.Min(float64(i+writeChunkSize), float64(len(request.GetBody().Deletes))))
+            end := int(math.Min(float64(i+deleteChunkSize), float64(len(request.GetBody().Deletes))))
config/clients/go/template/README_calling_api.mustache (6)

47-53: Fix missing method-chain dot.

Options(options)Execute() should be Options(options).Execute().

Apply this diff:

- store,  err := fgaClient.GetStore(context.Background()).Options(options)Execute()
+ store,  err := fgaClient.GetStore(context.Background()).Options(options).Execute()

183-190: Fix missing method-chain dot.

Options(options)Execute() should be Options(options).Execute().

Apply this diff:

- data, err := fgaClient.ReadLatestAuthorizationModel(context.Background()).Options(options)Execute()
+ data, err := fgaClient.ReadLatestAuthorizationModel(context.Background()).Options(options).Execute()

233-271: Incorrect variable name passed to Body().

You define body := ClientReadRequest{...} but call Body(requestBody). Use body to avoid a compile-time error in examples.

Apply this diff:

- data, err := fgaClient.Read(context.Background()).Body(requestBody).Options(options).Execute()
+ data, err := fgaClient.Read(context.Background()).Body(body).Options(options).Execute()

574-592: Mismatched variable name in ListObjects example.

You define body := ClientListObjectsRequest{...} but call Body(requestBody). Use body.

Apply this diff:

- data, err := fgaClient.ListObjects(context.Background()).
-   Body(requestBody).
+ data, err := fgaClient.ListObjects(context.Background()).
+   Body(body).
    Options(options).
    Execute()

609-623: Mismatched variable name in ListRelations example.

You define body := ClientListRelationsRequest{...} but call Body(requestBody). Use body.

Apply this diff:

- data, err := fgaClient.ListRelations(context.Background()).
-   Body(requestBody).
+ data, err := fgaClient.ListRelations(context.Background()).
+   Body(body).
    Options(options).
    Execute()

9-18: Unify package alias (openfga → {{packageName}}) and fix method-chain typos in README template.

  • Replace openfga.* usages with {{packageName}}.* in config/clients/go/template/README_calling_api.mustache at lines: 13, 543, 545, 607, 640, 645, 647, 650.
  • Fix broken method chaining (missing dot before Execute) in the same file at lines 52 and 189: change Options(... )Execute() → Options(...).Execute().
config/clients/go/template/client/client_test.mustache (1)

2719-2723: Leftover ‘openfga’ alias will not compile after alias switch.

These lines still reference openfga.PtrString and openfga.ExpandResponse, but the file imports {{packageName}} and not openfga. Replace with {{packageName}}.

Apply this diff:

-        options := ClientExpandOptions{
-            AuthorizationModelId: openfga.PtrString("01GAHCE4YVKPQEKZQHT2R89MQV"),
-        }
-
-        var expectedResponse openfga.ExpandResponse
+        options := ClientExpandOptions{
+            AuthorizationModelId: {{packageName}}.PtrString("01GAHCE4YVKPQEKZQHT2R89MQV"),
+        }
+
+        var expectedResponse {{packageName}}.ExpandResponse
🧹 Nitpick comments (5)
config/clients/go/CHANGELOG.md.mustache (1)

74-75: Fix stray “k” in compare link.

The URL currently has an extra “k” after {{gitRepoId}}.

Apply:

-### [0.6.2](https://{{gitHost}}/{{gitUserId}}/{{gitRepoId}}k/compare/v0.6.1...v0.6.2) (2024-10-21)
+### [0.6.2](https://{{gitHost}}/{{gitUserId}}/{{gitRepoId}}/compare/v0.6.1...v0.6.2) (2024-10-21)
config/clients/go/template/client/client.mustache (2)

1115-1120: Use pointer for Client in ReadLatestAuthorizationModel request (consistency).

Other request structs keep a pointer; align to avoid copying the client.

Apply:

-type SdkClientReadLatestAuthorizationModelRequest struct {
+type SdkClientReadLatestAuthorizationModelRequest struct {
   ctx    _context.Context
-  Client {{appShortName}}Client
+  Client *{{appShortName}}Client
   options *ClientReadLatestAuthorizationModelOptions
 }
@@
-  return &SdkClientReadLatestAuthorizationModelRequest{
-    Client: *client,
+  return &SdkClientReadLatestAuthorizationModelRequest{
+    Client: client,
     ctx:    ctx,
   }
@@
-  return request.Client.ReadLatestAuthorizationModelExecute(request)
+  return request.Client.ReadLatestAuthorizationModelExecute(request)

Also applies to: 1127-1129


2491-2526: Minor style nit: unify API field access.

Mixing client.{{appShortName}}Api and client.OpenFgaApi; prefer the templated form for consistency.

config/clients/go/template/README_calling_api.mustache (1)

364-398: New “Conflict Options” section looks good, but keep code style consistent.

  • Content is accurate and helpful.
  • Nit: elsewhere this doc uses “golang”; here it’s “go”. Pick one and use consistently.
config/clients/go/template/api_test.mustache (1)

790-1090: Solid coverage for OnDuplicate/OnMissing on WriteRequest.

  • Tests correctly assert presence and values of writes.on_duplicate and deletes.on_missing.
  • Optional: factor the repeated “register responder + decode body + assert field” into a small helper to reduce duplication and tighten failures.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d4c438 and e164445.

📒 Files selected for processing (9)
  • .github/workflows/main.yaml (1 hunks)
  • config/clients/go/CHANGELOG.md.mustache (1 hunks)
  • config/clients/go/config.overrides.json (1 hunks)
  • config/clients/go/template/README_calling_api.mustache (1 hunks)
  • config/clients/go/template/api_test.mustache (1 hunks)
  • config/clients/go/template/client/client.mustache (4 hunks)
  • config/clients/go/template/client/client_test.mustache (21 hunks)
  • config/clients/go/template/example/example1/example1.go (1 hunks)
  • config/clients/go/template/models_test.mustache (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
config/**/*.mustache

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Validate mustache syntax and variable references across all template files, including CHANGELOG.md.mustache

Files:

  • config/clients/go/template/api_test.mustache
  • config/clients/go/template/README_calling_api.mustache
  • config/clients/go/CHANGELOG.md.mustache
  • config/clients/go/template/models_test.mustache
  • config/clients/go/template/client/client.mustache
  • config/clients/go/template/client/client_test.mustache
config/**/*.{json,mustache}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Never hardcode API keys or credentials in configuration or template files

Files:

  • config/clients/go/template/api_test.mustache
  • config/clients/go/config.overrides.json
  • config/clients/go/template/README_calling_api.mustache
  • config/clients/go/CHANGELOG.md.mustache
  • config/clients/go/template/models_test.mustache
  • config/clients/go/template/client/client.mustache
  • config/clients/go/template/client/client_test.mustache
config/clients/*/config.overrides.json

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

config/clients/*/config.overrides.json: Always update the packageVersion in each language-specific config.overrides.json when making version changes
Maintain FOSSA compliance notice IDs in each language’s config.overrides.json

Files:

  • config/clients/go/config.overrides.json
config/{common/config.base.json,clients/*/config.overrides.json}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Ensure consistent versioning across base and language override configuration files to avoid version conflicts

Files:

  • config/clients/go/config.overrides.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build-and-test-java-sdk
  • GitHub Check: build-and-test-go-sdk
🔇 Additional comments (10)
.github/workflows/main.yaml (1)

68-69: Go job sets OPEN_API_REF — LGTM.

Matches PR description and scopes the override to the Go SDK tests step.

config/clients/go/CHANGELOG.md.mustache (2)

5-7: Changelog entry for conflict options — LGTM.

Clear note about server requirement and pointer to README.


5-7: Resolved — README anchor exists.
README template contains "Conflict Options for Write Operations" at config/clients/go/template/README_calling_api.mustache: line 364.

config/clients/go/template/client/client.mustache (1)

1705-1706: Propagate Conflict in chunked paths — LGTM.

Conflict options correctly flow to sub-requests.

Also applies to: 1751-1751

config/clients/go/template/example/example1/example1.go (1)

203-206: Good example usage of Conflict options.

Demonstrates ignoring duplicate writes clearly.

config/clients/go/config.overrides.json (2)

101-104: Addition of models_test.mustache — LGTM.

Improves coverage for WriteRequest and conflict defaults.


1-9: Verified — template exists and packageVersion is consistent.

models_test.mustache found at config/clients/go/template/models_test.mustache; config/clients/go/config.overrides.json packageVersion=0.7.1 and config/common/config.base.json has no packageVersion set (no mismatch).

config/clients/go/template/models_test.mustache (1)

1-759: Thorough model tests and sensible defaults.

Comprehensive checks for defaults, getters, setters, presence flags, and JSON marshalling for WriteRequest{Writes,Deletes} and WriteRequest. Nice.

config/clients/go/template/client/client_test.mustache (2)

15-16: Template package alias import LGTM.

Using {{packageName}} as the import alias keeps tests generation-friendly.


3562-3679: BatchCheck max-batch sizing tests look correct.

Validates request chunking count using MaxBatchSize/MaxParallelRequests; mutex around the counter is a good touch.

Comment thread config/clients/go/template/client/client_test.mustache
Comment thread config/clients/go/template/client/client.mustache Outdated
Comment thread config/clients/go/template/client/client.mustache
@rhamzeh
rhamzeh added this pull request to the merge queue Oct 8, 2025
Merged via the queue into main with commit 8e86a13 Oct 8, 2025
19 checks passed
@rhamzeh
rhamzeh deleted the feat/go-idempotent-writes branch October 8, 2025 16:33
@dyeam0 dyeam0 linked an issue Oct 23, 2025 that may be closed by this pull request
1 task
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.

[All SDKs] Add on_duplicate/on_missing options support for Write operations

2 participants