feat: add StreamedListObjects support
StreamedListObjects Implementation Summary
Issue: openfga/dotnet-sdk#110
Overview
Implemented StreamedListObjects functionality in the .NET SDK, providing feature parity with the JavaScript and Python SDKs.
What Was Implemented
Core Functionality
-
StreamedListObjectsmethod returningIAsyncEnumerable<StreamedListObjectsResponse> - NDJSON stream parser in
BaseClient - Support for all
ListObjectsparameters (authorization model ID, consistency, contextual tuples, context) - Proper resource cleanup on early termination and cancellation
- Full
CancellationTokensupport
Cross-Framework Support
- netstandard2.0
- net48
- net8.0
- net9.0
Files Changed
New Files
-
src/OpenFga.Sdk/Model/StreamedListObjectsResponse.cs -
src/OpenFga.Sdk.Test/ApiClient/StreamingTests.cs(11 tests) -
src/OpenFga.Sdk.Test/Client/StreamedListObjectsTests.cs(11 tests) -
example/StreamedListObjectsExample/(complete example application)
Modified Files
-
src/OpenFga.Sdk/ApiClient/BaseClient.cs- NDJSON streaming support -
src/OpenFga.Sdk/ApiClient/ApiClient.cs- Streaming request handling -
src/OpenFga.Sdk/Api/OpenFgaApi.cs- API endpoint -
src/OpenFga.Sdk/Client/Client.cs- Client-level method -
src/OpenFga.Sdk/Telemetry/Attributes.cs- Telemetry support -
src/OpenFga.Sdk/OpenFga.Sdk.csproj- AddedMicrosoft.Bcl.AsyncInterfacespackage -
CHANGELOG.md- Added feature entry
Test Results
All 22 tests passing (10 streaming + 11 client integration):
- NDJSON parsing (single/multi-line, chunked, invalid JSON handling)
- Empty lines and whitespace handling
- Resource cleanup and early termination
- Cancellation token support
- Error handling (HTTP errors, validation errors)
- Large dataset efficiency (100+ objects)
- All
ListObjectsoptions (consistency, contextual tuples, etc.)
Usage Example
await foreach (var response in fgaClient.StreamedListObjects(
new ClientListObjectsRequest {
User = "user:anne",
Relation = "can_read",
Type = "document"
},
new ClientListObjectsOptions {
Consistency = ConsistencyPreference.HIGHERCONSISTENCY
},
cancellationToken)) {
Console.WriteLine($"Received: {response.Object}");
}
Key Benefits
- No pagination limits - only constrained by server timeout
- Memory efficient - objects processed as they arrive
- Early termination - can break early with automatic cleanup
-
Idiomatic .NET - uses
IAsyncEnumerable<T>pattern
References
- API Documentation
- Example Application
- JavaScript SDK implementation review
- Python SDK implementation review
Summary by CodeRabbit
-
New Features
- Introduced StreamedListObjects API method enabling incremental object retrieval as items arrive
- Supports all ListObjects parameters: authorization model ID, consistency preferences, contextual tuples, and context data
- Includes resource cleanup on early termination and cancellation token support
-
Documentation
- Added comprehensive StreamedListObjects usage example with streaming patterns and best practices
[!IMPORTANT]
Review skipped
Auto incremental reviews are disabled on this repository.
Please check the settings in the CodeRabbit UI or the
.coderabbit.yamlfile in this repository. To trigger a single review, invoke the@coderabbitai reviewcommand.You can disable this status message by setting the
reviews.review_statustofalsein the CodeRabbit configuration file.
Walkthrough
Introduces streaming support to the OpenFGA .NET SDK via a new StreamedListObjects method returning IAsyncEnumerable<StreamedListObjectsResponse>. Adds NDJSON parsing infrastructure, cancellation support, resource cleanup, and comprehensive test coverage across API, client, and infrastructure layers.
Changes
| Cohort / File(s) | Summary |
|---|---|
Streaming Infrastructure src/OpenFga.Sdk/ApiClient/BaseClient.cs, src/OpenFga.Sdk/ApiClient/ApiClient.cs |
Adds streaming API methods SendStreamingRequestAsync<T> to parse NDJSON responses line-by-line, handle cancellation, propagate errors, and yield parsed objects incrementally; supports optional header injection and error handling consistent with existing patterns. |
API Layer src/OpenFga.Sdk/Api/OpenFgaApi.cs |
Introduces StreamedListObjects method mirroring ListObjects but streaming results via /stores/{store_id}/streamed-list-objects endpoint; validates store ID, constructs query parameters, and yields items via SendStreamingRequestAsync. |
Client Facade src/OpenFga.Sdk/Client/Client.cs |
Adds StreamedListObjects method to OpenFgaClient that delegates to api.StreamedListObjects with request/options conversion and EnumeratorCancellation support. |
Model src/OpenFga.Sdk/Model/StreamedListObjectsResponse.cs |
Introduces StreamedListObjectsResponse class with Object property (serialized as "object"), JSON (de)serialization, equality/hashing, and validation support for streamed items. |
Streaming Infrastructure Tests src/OpenFga.Sdk.Test/ApiClient/StreamingTests.cs |
Comprehensive unit tests for BaseClient.SendStreamingRequestAsync covering NDJSON parsing, single/multiple lines, empty/whitespace handling, cancellation, HTTP error propagation, early resource disposal, and invalid JSON edge cases. |
Integration Tests src/OpenFga.Sdk.Test/Client/StreamedListObjectsTests.cs |
Adds 12 test cases for OpenFgaClient.StreamedListObjects validating incremental streaming, parameter inclusion (authorization model ID, consistency, contextual tuples), error handling, resource cleanup, cancellation, empty responses, validation errors, and efficient large-scale streaming. |
Example & Documentation example/StreamedListObjectsExample/StreamedListObjectsExample.cs, example/StreamedListObjectsExample/README.md, example/StreamedListObjectsExample/StreamedListObjectsExample.csproj |
Adds runnable example program demonstrating StreamedListObjects usage patterns including normal streaming, early termination, cancellation via CancellationTokenSource, and cleanup; includes project file with .NET 9.0 target and dependency configuration. |
Configuration & Telemetry src/OpenFga.Sdk/OpenFga.Sdk.csproj, src/OpenFga.Sdk/Telemetry/Attributes.cs |
Adds Microsoft.Bcl.AsyncInterfaces 8.0.0 package dependency; expands telemetry attribute processing to include StreamedListObjects for request body and user extraction. |
Changelog CHANGELOG.md |
Documents new StreamedListObjects feature in Unreleased section with description of streaming behavior, parameter support, and resource cleanup guarantees. |
Sequence Diagram
sequenceDiagram
participant Caller
participant OpenFgaClient
participant OpenFgaApi
participant ApiClient
participant BaseClient
participant HttpClient
participant NDJSON Stream
Caller->>OpenFgaClient: StreamedListObjects(request, options)
OpenFgaClient->>OpenFgaApi: StreamedListObjects(storeId, body, options, cancellationToken)
OpenFgaApi->>ApiClient: SendStreamingRequestAsync<ListObjectsRequest, StreamedListObjectsResponse>
ApiClient->>ApiClient: GetAuthenticationToken()
ApiClient->>BaseClient: SendStreamingRequestAsync<ListObjectsRequest, StreamedListObjectsResponse>
BaseClient->>HttpClient: SendAsync(request, HttpCompletionOption.ResponseHeadersRead)
HttpClient->>NDJSON Stream: Stream response body (NDJSON)
loop For each line in stream
NDJSON Stream->>BaseClient: Read line
alt Valid JSON with "result"
BaseClient->>BaseClient: Parse JSON, extract result
BaseClient->>ApiClient: Yield<StreamedListObjectsResponse>
ApiClient->>OpenFgaApi: Yield<StreamedListObjectsResponse>
OpenFgaApi->>OpenFgaClient: Yield<StreamedListObjectsResponse>
OpenFgaClient->>Caller: Yield<StreamedListObjectsResponse>
else Empty/Whitespace line
BaseClient->>BaseClient: Skip line
else Invalid JSON
BaseClient->>BaseClient: Skip line (log if applicable)
else Cancellation requested
BaseClient->>BaseClient: Break loop, dispose stream
else HTTP error status
BaseClient->>BaseClient: Throw ApiException via CreateSpecificExceptionAsync
end
end
Caller->>Caller: Complete iteration or break early
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~45–75 minutes
- BaseClient.cs: Dense NDJSON streaming logic with line-by-line parsing, JSON deserialization, error recovery (skipping invalid lines), cancellation handling, and response status validation requires careful verification of edge cases.
- StreamingTests.cs: Comprehensive test suite covering 10 scenarios (single/multiple lines, empty lines, cancellation, HTTP errors, early disposal, whitespace, invalid JSON) with mocked HTTP responses; verify test coverage completeness and mocking strategy.
- StreamedListObjectsTests.cs: 12 integration tests with mock HTTP handler and NDJSON response creation; validate request construction (path, method, headers), parameter encoding, and error/edge-case assertions.
- ApiClient.cs and OpenFgaApi.cs: Verify token acquisition, header construction, and delegation patterns align with existing non-streaming request paths; confirm no regression in authentication flow.
-
Telemetry attributes expansion: Confirm
StreamedListObjectsis added to all relevant conditions consistently.
Possibly related PRs
- openfga/dotnet-sdk#133: Modifies per-request header construction and propagation in
ApiClient,OpenFgaApi, andClientclasses, which overlaps with the streaming header-building logic in this PR.
Suggested labels
enhancement
Suggested reviewers
- evansims
- rhamzeh
- ewanharris
Pre-merge checks and finishing touches
✅ 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: add StreamedListObjects support' directly and clearly describes the main feature addition in this PR: implementing StreamedListObjects streaming API support. |
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.
Comment @coderabbitai help to get the list of available commands and usage tips.