Skip to content

feat(dotnet-sdk): Added support for an interface on the client#168

Merged
SoulPancake merged 5 commits intoopenfga:mainfrom
CharlieDigital:main
Dec 11, 2025
Merged

feat(dotnet-sdk): Added support for an interface on the client#168
SoulPancake merged 5 commits intoopenfga:mainfrom
CharlieDigital:main

Conversation

@CharlieDigital
Copy link
Copy Markdown
Contributor

@CharlieDigital CharlieDigital commented Dec 11, 2025

Provides an interface for the OpenFgaClient to improve testability in DI scenarios by allowing mocks and substitutes to be created.

(Redux: #158)

Description

What problem is being solved?

It is currently not possible to mock the OpenFgaClient in unit tests in .NET as its methods are not virtual and it does not provide an interface for mocking

How is it being solved?

This PR adds an interface extracted from the OpenFgaClient

What changes are made to solve it?

  • Added an interface for the OpenFgaClient
  • Reformatted comments to be idiomatic C# comment style for editor support
  • Changed implementation comments to <inheritdoc />

References

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 batch check capabilities for efficient parallel permission validation
    • Extended cancellation token support across API methods for better timeout control
  • Improvements

    • Enhanced parallel processing with improved error handling and validation
    • Strengthened request validation including correlation ID uniqueness checks
    • Better error propagation for batch operations

✏️ Tip: You can customize this high-level summary in your review settings.

@CharlieDigital CharlieDigital requested a review from a team as a code owner December 11, 2025 14:05
Copilot AI review requested due to automatic review settings December 11, 2025 14:05
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Dec 11, 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.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

The changes introduce a new public interface IOpenFgaClient and refactor the OpenFgaClient class to implement it. The API surface has been standardized with consistent CancellationToken parameters, enhanced batch processing capabilities (client-side and server-side), and improved parallel processing with .NET 6.0+ support and fallback throttling.

Changes

Cohort / File(s) Change Summary
New Interface Definition
src/OpenFga.Sdk/Client/IOpenFgaClient.cs
Introduces comprehensive IOpenFgaClient interface with ~25+ public async methods covering store management, authorization models, reads/writes, checks, batch operations (ClientBatchCheck, BatchCheck), expansions, object/relation/user listing, and assertions management. All methods accept CancellationToken and options objects with defaults.
Client Implementation Refactor
src/OpenFga.Sdk/Client/Client.cs
Refactors OpenFgaClient to implement IOpenFgaClient interface. Standardizes public API with CancellationToken parameters and options objects. Adds batch processing logic with client-side and server-side paths, correlation ID validation, and chunking. Implements parallel processing using Parallel.ForEachAsync (NET6.0_OR_GREATER) and SemaphoreSlim fallback. Updates method signatures across stores, models, reads, writes, checks, expansions, and assertions operations.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Interface Design: Review the new IOpenFgaClient interface contract, method signatures, parameter patterns, and documentation coverage across ~25+ methods.
  • Batch Processing Logic: Validate correlation ID uniqueness checking, transformation of checks to batch items, chunking strategy, parallel batch request processing, and response mapping.
  • Parallel Processing Implementation: Examine the conditional NET6.0_OR_GREATER path using Parallel.ForEachAsync with structured cancellation, fallback SemaphoreSlim throttling, and per-item error propagation.
  • Data Mapping Updates: Review consistency of field population (TupleKey, ContextualTuples, AuthorizationModelId) across multiple operation types and optional field handling.
  • Error Handling: Verify proper exception propagation in batch operations and parallel processing paths.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(dotnet-sdk): Added support for an interface on the client' directly summarizes the main change: introducing an interface for the OpenFgaClient to improve testability, which aligns with the PR's primary objective.
Docstring Coverage ✅ Passed Docstring coverage is 80.36% which is sufficient. The required threshold is 80.00%.

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.

@dosubot
Copy link
Copy Markdown

dosubot bot commented Dec 11, 2025

Related Documentation

Checked 7 published document(s) in 1 knowledge base(s). No updates required.

How did I do? Any feedback?  Join Discord

Copy link
Copy Markdown

@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: 2

🧹 Nitpick comments (4)
src/OpenFga.Sdk/Client/IOpenFgaClient.cs (2)

15-16: Consider extending IDisposable for resource management.

The OpenFgaClient class implements IDisposable, but IOpenFgaClient does not extend it. This means consumers using the interface cannot properly dispose of resources without casting to the concrete type, which defeats the purpose of the abstraction for DI scenarios.

-public interface IOpenFgaClient
+public interface IOpenFgaClient : IDisposable

1-5: Using directives ordering.

Minor: The System.* namespaces are typically placed before project-specific namespaces in C# conventions. Consider reordering for consistency.

-using OpenFga.Sdk.Client.Model;
-using OpenFga.Sdk.Model;
 using System.Collections.Generic;
 using System.Threading;
 using System.Threading.Tasks;
+using OpenFga.Sdk.Client.Model;
+using OpenFga.Sdk.Model;
src/OpenFga.Sdk/Client/Client.cs (2)

757-812: Consider using ConcurrentBag instead of List with locking for consistency.

This method uses List<ClientBatchCheckSingleResponse> with explicit lock statements (line 791), while other parallel processing methods (ProcessWriteChunksAsync, ProcessCheckRequestsAsync) use ConcurrentBag<T> for thread-safe collection of results.

The current approach works correctly, but using ConcurrentBag would be more consistent with the rest of the codebase and avoid the locking overhead.

Change the parameter type and remove the lock:

 private async Task ProcessBatchAsync(
     List<BatchCheckItem> batch,
     IClientBatchCheckOptions? options,
     Dictionary<string, string> headers,
     Dictionary<string, ClientBatchCheckItem> correlationIdToCheck,
-    List<ClientBatchCheckSingleResponse> results,
+    ConcurrentBag<ClientBatchCheckSingleResponse> results,
     CancellationToken cancellationToken
 )

And update the result handling:

         if (batchResponse.Result != null)
         {
-            lock (results)
-            {
                 foreach (var kvp in batchResponse.Result)
                 {
                     // ...
-                    results.Add(
+                    results.Add(
                         new ClientBatchCheckSingleResponse(...)
                     );
                 }
-            }
         }

31-32: Minor: Extra space in XML doc comments.

The /// <inheritdoc/> comments have an extra space after ///. This is inconsistent with standard C# XML documentation conventions and may cause issues with some documentation tools.

-    ///  <inheritdoc/>
+    /// <inheritdoc/>

This pattern appears throughout the file on multiple methods.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1deeeeb and 0768e6e.

📒 Files selected for processing (2)
  • src/OpenFga.Sdk/Client/Client.cs (12 hunks)
  • src/OpenFga.Sdk/Client/IOpenFgaClient.cs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/OpenFga.Sdk/Client/IOpenFgaClient.cs (7)
src/OpenFga.Sdk/Client/Model/ClientCreateStoreRequest.cs (1)
  • ClientCreateStoreRequest (6-7)
src/OpenFga.Sdk/Client/Model/ClientWriteAuthorizationModelRequest.cs (1)
  • ClientWriteAuthorizationModelRequest (6-7)
src/OpenFga.Sdk/Client/Model/ClientReadChangesOptions.cs (1)
  • ClientReadChangesOptions (12-24)
src/OpenFga.Sdk/Client/Model/ClientReadRequest.cs (1)
  • ClientReadRequest (5-6)
src/OpenFga.Sdk/Client/Model/ClientWriteResponse.cs (1)
  • ClientWriteResponse (133-134)
src/OpenFga.Sdk/Model/JsonStringEnumMemberConverter.cs (1)
  • Write (60-62)
src/OpenFga.Sdk/Client/Model/ClientWriteAssertionsRequest.cs (1)
  • ClientAssertion (83-84)
⏰ 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: CodeQL analysis (csharp)
  • GitHub Check: Agent
🔇 Additional comments (8)
src/OpenFga.Sdk/Client/Client.cs (8)

47-99: LGTM!

The parallel processing implementation correctly uses Parallel.ForEachAsync with proper cancellation token propagation and degree of parallelism control. The error handling appropriately marks all items in a failed chunk with the exception.


146-208: LGTM!

The semaphore-based fallback implementation for older .NET frameworks correctly handles throttling with proper disposal and release patterns.


634-668: LGTM - Good input validation.

The validation for empty checks, MaxBatchSize, and MaxParallelRequests prevents invalid configurations and potential deadlocks. The bulkRequestId generation for request tracking is a good practice.


869-923: LGTM!

The ListRelations method correctly validates input and uses ClientBatchCheck to parallelize relation checks. The error handling propagates the first encountered error appropriately.


467-555: LGTM!

The Write method correctly handles both transactional (single batch) and non-transactional (chunked parallel) paths with proper response mapping and cancellation token propagation.


20-45: LGTM!

The class declaration, constructor, properties, and disposal implementation are well-structured. The protected access modifier for the api field allows for extension through subclassing if needed.


394-419: LGTM!

The implementation correctly fetches the latest authorization model by requesting only one item and handling the empty case appropriately.


575-603: LGTM!

The Check method correctly constructs the request with tuple key, contextual tuples, context, authorization model ID, and consistency options.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces an IOpenFgaClient interface to enable mocking and dependency injection scenarios for the OpenFGA .NET SDK. The interface extracts all public methods and properties from the OpenFgaClient class, allowing developers to create mocks and substitutes for unit testing.

Key Changes

  • Adds IOpenFgaClient interface with 22 method signatures and 2 properties
  • Updates OpenFgaClient to implement IOpenFgaClient
  • Replaces XML documentation comments with <inheritdoc/> tags in the implementation

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.

File Description
src/OpenFga.Sdk/Client/IOpenFgaClient.cs New interface defining all public methods and properties of OpenFgaClient, enabling mocking for unit tests
src/OpenFga.Sdk/Client/Client.cs Implements IOpenFgaClient interface, reformats code for consistency, and replaces documentation with inheritdoc tags

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Member

@SoulPancake SoulPancake left a comment

Choose a reason for hiding this comment

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

Thank you so much @CharlieDigital

@SoulPancake SoulPancake added this pull request to the merge queue Dec 11, 2025
Merged via the queue into openfga:main with commit c119407 Dec 11, 2025
22 checks passed
@CharlieDigital
Copy link
Copy Markdown
Contributor Author

Nice! Will make our integration testing scenarios much easier :)

Copilot AI mentioned this pull request Jan 26, 2026
4 tasks
@coderabbitai coderabbitai bot mentioned this pull request Feb 4, 2026
4 tasks
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.

Provide client service through interfaces to improve decoupling and testability of client application

4 participants