bitplatform icon indicating copy to clipboard operation
bitplatform copied to clipboard

Made ReadUserSessionLogs stream logs with IAsyncEnumerable

Open Kyemate opened this issue 2 months ago • 1 comments

closes #11480

Summary by CodeRabbit

  • Improvements
    • Diagnostic logs now stream incrementally, providing faster initial response times when retrieving user session logs.
    • Added cancellation support for log retrieval operations, enabling users to stop ongoing requests.

Kyemate avatar Oct 30 '25 23:10 Kyemate

[!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

The user session logs retrieval is converted from batch-based RPC to SignalR streaming. The server method now uses IAsyncEnumerable<DiagnosticLogDto> to yield logs incrementally rather than returning all logs at once. The client consumes logs via StreamAsync and processes them as they arrive, with full cancellation support.

Changes

Cohort / File(s) Summary
Server streaming conversion
src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/SignalR/AppHub.cs
Method GetUserSessionLogs signature changed from Task<DiagnosticLogDto[]> to IAsyncEnumerable<DiagnosticLogDto>. Added [EnumeratorCancellation] CancellationToken parameter. Implemented streaming enumeration with per-log cancellation checks. Changed error handling to yield break when connection ID not found. Added System.Runtime.CompilerServices directive.
Client streaming consumption
src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Pages/Management/UsersPage.razor.cs
Replaced direct RPC call with hubConnection.StreamAsync<DiagnosticLogDto>("GetUserSessionLogs", ...) using await foreach loop. Each received log is enqueued into DiagnosticLogger.Store incrementally. Cancellation token now properly respected throughout stream lifetime.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client<br/>(UsersPage)
    participant Hub as Server<br/>(AppHub)
    participant DB as Database

    rect rgb(230, 245, 240)
    Note over Client,DB: New Streaming Approach
    Client->>Hub: StreamAsync("GetUserSessionLogs", id, token)
    activate Hub
    Hub->>DB: Query connection ID (with token)
    DB-->>Hub: Connection ID
    loop For Each Log
        Hub->>Hub: Fetch next log via InvokeAsync
        Hub->>Hub: Check cancellation
        Hub-->>Client: yield DiagnosticLogDto
        activate Client
        Client->>Client: Enqueue to DiagnosticLogger.Store
        deactivate Client
    end
    Hub-->>Client: Stream complete
    deactivate Hub
    Client->>Client: Publish SHOW_DIAGNOSTIC_MODAL
    end

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Method signature changes: GetUserSessionLogs converted from Task<T[]> return to IAsyncEnumerable<T>, requiring verification that all callers handle streaming correctly
  • Cancellation token handling: Review [EnumeratorCancellation] attribute usage and per-log cancellation checks to ensure proper propagation
  • Error handling pattern shift: Verify that yield break (instead of empty array return) is handled correctly by all consumers
  • Stream lifecycle: Confirm that the client-side await foreach properly completes and triggers modal publication

Poem

🐰 Logs now flow like streams so wide,
No more bursting at the seide!
Each message drifts down, bit by bit,
The socket smiles—what perfect fit!
SignalR's heart skips with delight,
As batches transform to flowing light. 🌊

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title "Made ReadUserSessionLogs stream logs with IAsyncEnumerable" directly captures the primary change in the changeset. The code modifications convert GetUserSessionLogs from a synchronous-style return of all logs (Task<DiagnosticLogDto[]>) to a streaming approach using IAsyncEnumerable<DiagnosticLogDto>, which is exactly what the title communicates. While there is a minor semantic difference between "Read" in the title and "Get" in the actual method name, this does not undermine the title's accuracy since both terms semantically relate to the functionality of retrieving user session logs. The title is concise, clear, and specific enough for a teammate to understand the core change.
Linked Issues Check ✅ Passed The linked issue #11480 describes a SignalR message size error ("The maximum message size of 32768B was exceeded") that occurs when reading another user's log through user management. The root cause is that all logs are returned in a single message, exceeding the size limit. The PR directly addresses this by converting GetUserSessionLogs from returning a Task<DiagnosticLogDto[]> (all logs at once) to an IAsyncEnumerable<DiagnosticLogDto> that streams logs individually to the client via hubConnection.StreamAsync(). This architectural change ensures that logs are transmitted incrementally rather than in a single large message, effectively bypassing the message size constraint. The addition of cancellation token support is also a beneficial enhancement that aligns with best practices for async streaming operations.
Out of Scope Changes Check ✅ Passed All code changes in the pull request are directly related to implementing the streaming solution for issue #11480. The modifications in UsersPage.razor.cs replace the direct RPC call with a streaming pattern using hubConnection.StreamAsync(), while the changes in AppHub.cs convert the GetUserSessionLogs method to return IAsyncEnumerable<DiagnosticLogDto> with streaming implementation. The addition of the System.Runtime.CompilerServices using directive is necessary to support the [EnumeratorCancellation] attribute required for proper cancellation handling in async enumerable methods. No extraneous changes, refactoring, or unrelated modifications are present in the changeset.

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.

coderabbitai[bot] avatar Oct 30 '25 23:10 coderabbitai[bot]