Skip to content

agents: DRY DelegateAsyncExport to use templates#294

Closed
santigimeno wants to merge 1 commit intonode-v22.x-nsolid-v5.xfrom
santi/dry_grpc_client
Closed

agents: DRY DelegateAsyncExport to use templates#294
santigimeno wants to merge 1 commit intonode-v22.x-nsolid-v5.xfrom
santi/dry_grpc_client

Conversation

@santigimeno
Copy link
Copy Markdown
Member

@santigimeno santigimeno commented Apr 22, 2025

This commit refactors the GrpcClient::DelegateAsyncExport method to use templates instead of having multiple overloaded implementations for each event type.

This change significantly reduces code duplication while maintaining the same functionality, making the codebase more maintainable and less prone to errors when adding new event types.

Summary by CodeRabbit

  • Refactor
    • Streamlined asynchronous event export handling by consolidating multiple event-specific calls into a single generic method, enhancing internal efficiency and maintainability without affecting user experience.

@santigimeno santigimeno self-assigned this Apr 22, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 22, 2025

Walkthrough

The changes refactor the gRPC asynchronous export mechanism for various event types in the codebase. The implementation of the templated asynchronous call handler (GrpcAsyncCallData) and the generic DelegateAsyncExport method are moved from the source file to the header file, consolidating multiple event-specific overloads into a single template method. All call sites in the agent are updated to use this new templated approach, passing the appropriate export method pointer for each event type. This update centralizes and generalizes the asynchronous export logic, removing redundancy and improving maintainability.

Changes

File(s) Change Summary
agents/grpc/src/grpc_agent.cc Updated all gRPC event export calls to use the new templated DelegateAsyncExport method, passing the specific async export method pointer for each event type.
agents/grpc/src/grpc_client.cc Removed the template class GrpcAsyncCallData, the template function InternalDelegateAsyncExport, and all explicit instantiations of DelegateAsyncExport for specific event types.
agents/grpc/src/grpc_client.h Added the template class GrpcAsyncCallData and a single generic templated DelegateAsyncExport method. Removed multiple event-specific overloads and consolidated logic into the template. Added assertions for pointer validity.

Poem

In the warren of code, templates now gleam,
One method to rule, where many once teemed.
The agent dispatches with elegant flair,
Exporting events with much less to spare.
Redundant old tunnels have faded from view—
This rabbit approves, and hops on anew!
🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6b2db83 and 43911c9.

📒 Files selected for processing (3)
  • agents/grpc/src/grpc_agent.cc (10 hunks)
  • agents/grpc/src/grpc_client.cc (0 hunks)
  • agents/grpc/src/grpc_client.h (3 hunks)
💤 Files with no reviewable changes (1)
  • agents/grpc/src/grpc_client.cc
🚧 Files skipped from review as they are similar to previous changes (1)
  • agents/grpc/src/grpc_agent.cc
🧰 Additional context used
🧬 Code Graph Analysis (1)
agents/grpc/src/grpc_client.h (1)
agents/grpc/src/proto/nsolid_service.grpc.pb.h (13)
  • context (38-40)
  • context (38-38)
  • context (41-43)
  • context (41-41)
  • context (44-46)
  • context (44-44)
  • context (47-49)
  • context (47-47)
  • context (50-52)
  • context (50-50)
  • context (53-55)
  • context (53-53)
  • context (56-58)
🔇 Additional comments (4)
agents/grpc/src/grpc_client.h (4)

25-50: Clean encapsulation of asynchronous call state.

The GrpcAsyncCallData template class provides a neat encapsulation of all the state needed for asynchronous gRPC calls. Moving it from the source file to the header is appropriate for template visibility. The class correctly declares copy and move operations as deleted to prevent unintended copies.


72-83: Good documentation with usage example.

The documentation clearly explains the purpose of the templated method and includes a practical example of how to use it. This will be helpful for maintaining consistency in future call sites.


102-108: Good fix for error handling.

The code now properly checks for allocation failures and returns an error code instead of using assertions. This is proper production error handling and addresses a previous review comment.


112-125: Clean implementation of asynchronous call delegation.

The implementation properly:

  1. Calls the specified export method on the stub
  2. Sets up the completion lambda to store the status and invoke the user's callback
  3. Returns the appropriate success code

The templated approach effectively reduces code duplication while preserving functionality, which was the main goal of this PR.

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 1

🔭 Outside diff range comments (1)
agents/grpc/src/grpc_agent.cc (1)

1748-1757: ⚠️ Potential issue

Pass arena‑allocated pointer, not a copy

Each of these call‑sites dereferences the arena‑allocated message and passes std::move(*event) into DelegateAsyncExport.
After refactor (and to fix the dangling‑pointer problem highlighted in grpc_client.h) you should pass the pointer itself:

-    std::move(context), std::move(arena), std::move(*event),
+    std::move(context), std::move(arena), event,

No copy is performed, lifetime is tied to the arena that call_data already owns, and the template signature becomes:

DelegateAsyncExport<grpcagent::BlockedLoopEvent>(
    stub, &grpc_async::ExportBlockedLoop,
    std::move(ctx), std::move(arena), event, cb);

Search‑and‑replace for all nine similar occurrences shown in this hunk.

Also applies to: 1797-1800, 1841-1844, 1869-1872, 1892-1895, 1916-1919, 1967-1970, 1990-1993, 2015-2018

🧹 Nitpick comments (3)
agents/grpc/src/grpc_client.h (1)

98-111: Prefer RAII over raw new / delete for event_response

event_response is heap‑allocated with new and manually deleted after the user callback.
Consider wrapping it in a std::unique_ptr<grpcagent::EventResponse> (or store it directly inside GrpcAsyncCallData) to make ownership explicit and exception‑safe.

-  grpcagent::EventResponse* event_response = nullptr;
+  std::unique_ptr<grpcagent::EventResponse> event_response;

and adjust the lambda to pass event_response.get().

A minor change, but it eliminates a fragile manual delete.

agents/grpc/src/grpc_agent.cc (1)

53-54: Alias name can be more explicit

using grpc_async = ...::async_interface; shortens the code nicely, but the very generic name grpc_async can clash in wider scopes.
Consider something like NSolidAsyncStub or GrpcNSolidAsync to make its provenance clear.

agents/grpc/src/grpc_client.cc (1)

82-83: Remove stale comments once refactor stabilises

Good to keep a migration note during review, but once the header houses the templates permanently these comments can be pruned to avoid drift.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 354e74b and a8803ab.

📒 Files selected for processing (3)
  • agents/grpc/src/grpc_agent.cc (10 hunks)
  • agents/grpc/src/grpc_client.cc (1 hunks)
  • agents/grpc/src/grpc_client.h (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: lint-js-and-md
  • GitHub Check: build-docs
  • GitHub Check: coverage-windows

Comment thread agents/grpc/src/grpc_client.h
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: 0

🧹 Nitpick comments (3)
.github/workflows/build-tarball.yml (1)

108-108: Simplify TEST_CI_ARGS and remove extra spacing
Removing the deprecated --node-args flag and condensing the argument string.

Apply this minimal diff to clean up the double space:

- TEST_CI_ARGS="-p dots  --measure-flakiness 9"
+ TEST_CI_ARGS="-p dots --measure-flakiness 9"
.github/workflows/coverage-linux.yml (1)

73-74: Simplify TEST_CI_ARGS and tolerate inspector-related failures
Removed the explicit --node-args option and added || exit 0 to let coverage collection proceed despite known inspector test failures.

Consider trimming the extra space:

- TEST_CI_ARGS="-p dots  --measure-flakiness 9"
+ TEST_CI_ARGS="-p dots --measure-flakiness 9"
.github/workflows/coverage-linux-without-intl.yml (1)

73-74: Simplify TEST_CI_ARGS and allow coverage step to continue
Removed obsolete --node-args and ensured failures don’t block coverage upload.

You may also trim the double space:

- TEST_CI_ARGS="-p dots  --measure-flakiness 9"
+ TEST_CI_ARGS="-p dots --measure-flakiness 9"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a8803ab and cb0f825.

📒 Files selected for processing (5)
  • .github/workflows/build-tarball.yml (4 hunks)
  • .github/workflows/coverage-linux-without-intl.yml (2 hunks)
  • .github/workflows/coverage-linux.yml (2 hunks)
  • .github/workflows/test-linux.yml (1 hunks)
  • .github/workflows/test-macos.yml (5 hunks)
🧰 Additional context used
🪛 actionlint (1.7.4)
.github/workflows/test-linux.yml

42-42: label "ubuntu-24.04-arm" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)

⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: test-tarball-linux
  • GitHub Check: coverage-windows
  • GitHub Check: coverage-linux
  • GitHub Check: test-linux (ubuntu-24.04-arm)
  • GitHub Check: coverage-linux-without-intl
  • GitHub Check: test-macOS
  • GitHub Check: test-linux (ubuntu-24.04)
🔇 Additional comments (32)
.github/workflows/build-tarball.yml (5)

49-49: Upgrade to actions/setup-python v5.4.0
Bumping to the latest patch release for setup-python ensures compatibility with Python 3.12.


53-53: Upgrade sccache-action to v0.0.8
The newer version includes bugfixes and performance improvements for caching compilation artifacts.


55-55: Bump sccache version to v0.10.0
Updating to the latest sccache release to leverage improved cache backend support.


67-67: Upgrade upload-artifact to v4.6.1
Aligns with other workflows and pulls in incremental fixes.


89-89: Upgrade download-artifact to v4.1.9
Keeps artifact download in sync with upload step and addresses recent stability patches.

.github/workflows/coverage-linux.yml (5)

57-57: Upgrade to actions/setup-python v5.4.0
Consistent with other CI workflows; ensures Python 3.12 support.


61-61: Upgrade sccache-action to v0.0.8
Brings in the latest cache improvements for C/C++ builds.


63-63: Bump sccache version to v0.10.0
Matches the version used in other workflows for consistency.


75-77: Add JavaScript coverage reporting step
Running npx c8 report --check-coverage with increased memory helps enforce JS coverage thresholds.


84-84: Upgrade codecov-action to v5.4.0
Ensures compatibility with the latest Codecov API and reporting features.

.github/workflows/coverage-linux-without-intl.yml (5)

57-57: Upgrade to actions/setup-python v5.4.0
Aligns with the main coverage workflow for Python 3.12 support.


61-61: Upgrade sccache-action to v0.0.8
Consistent cache behavior across workflows.


63-63: Bump sccache version to v0.10.0
Keeps sccache at the latest stable release.


75-77: Add JavaScript coverage reporting step
Using npx c8 report --check-coverage with extra Node memory to enforce coverage rules.


84-84: Upgrade codecov-action to v5.4.0
Matches other workflows for consistent Codecov integration.

.github/workflows/test-linux.yml (7)

38-43: Verify availability of the ubuntu-24.04-arm runner label
Dynamic runs-on: ${{ matrix.os }} is correct for matrix builds, but the label ubuntu-24.04-arm may not exist on GitHub-hosted runners. Confirm it’s provided via self-hosted or update the label if needed.

🧰 Tools
🪛 actionlint (1.7.4)

42-42: label "ubuntu-24.04-arm" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)


47-48: Clone repository into node/ subdirectory
Ensures isolation of Node-specific build and test steps.


49-51: Upgrade to actions/setup-python v5.4.0
Consistent with other CI workflows for Python 3.12.


53-55: Upgrade sccache-action to v0.0.8 & bump version to v0.10.0
Keeps caching aligned with other workflows.


59-59: Run build inside node/ directory
Correctly scopes the make invocation to the cloned subdirectory.


61-61: Simplify TEST_CI_ARGS for Linux tests
Removed deprecated flags and standardized on -p actions --measure-flakiness 9.


63-69: Add robustness test in directory with special characters
Rerunning tests in a path containing unusual characters helps catch path-encoding issues in the test harness.

.github/workflows/test-macos.yml (10)

33-33: Add XCODE_VERSION environment variable
Pinning Xcode to 16.1 ensures consistent build environment on macOS runners.


42-43: Disable fail-fast in matrix build
Allows both jobs to complete on failures, improving parallel feedback.


53-54: Clone repository into node/ subdirectory
Aligns with Linux CI structure for Node-based builds.


55-57: Upgrade to actions/setup-python v5.4.0
Standardizes Python setup across platforms.


58-60: Add Xcode toolchain selection step
Switches to the specified Xcode app path for builds and simulator runs.


61-63: Upgrade sccache-action to v0.0.8 & bump version to v0.10.0
Brings caching improvements to macOS build steps.


73-73: Pre-warm tools/doc/node_modules to surface failures early
Good strategy to catch flaky npm ci errors before the main build.


89-89: Run build inside node/ directory on macOS
Correctly scopes the invocation to the cloned subdirectory.


93-93: Simplify TEST_CI_ARGS for macOS tests
Standardized on -p actions --measure-flakiness 9 and removed legacy flags.


95-100: Add robustness test in directory with special characters
Mirrors Linux workflow to catch path-encoding issues on macOS.

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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cb0f825 and a99e192.

📒 Files selected for processing (3)
  • agents/grpc/src/grpc_agent.cc (10 hunks)
  • agents/grpc/src/grpc_client.cc (0 hunks)
  • agents/grpc/src/grpc_client.h (2 hunks)
💤 Files with no reviewable changes (1)
  • agents/grpc/src/grpc_client.cc
🚧 Files skipped from review as they are similar to previous changes (1)
  • agents/grpc/src/grpc_agent.cc
⏰ Context from checks skipped due to timeout of 90000ms (8)
  • GitHub Check: build-tarball
  • GitHub Check: test-macOS
  • GitHub Check: test-linux (ubuntu-24.04-arm)
  • GitHub Check: test-linux (ubuntu-24.04)
  • GitHub Check: coverage-linux-without-intl
  • GitHub Check: coverage-linux
  • GitHub Check: coverage-windows
  • GitHub Check: lint-js-and-md

Comment thread agents/grpc/src/grpc_client.h Outdated
Comment thread agents/grpc/src/grpc_client.h
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: 1

🔭 Outside diff range comments (1)
agents/grpc/src/grpc_client.h (1)

4-8: ⚠️ Potential issue

Missing direct include for google::protobuf::Arena

Arena is used via using google::protobuf::Arena; but its header (google/protobuf/arena.h) is not included. Relying on transitive inclusion from generated protobuf headers is brittle and can break when those headers change.

+#include <google/protobuf/arena.h>

Add this include just above the existing protobuf/gRPC headers to ensure the file builds in isolation.

🧹 Nitpick comments (1)
agents/grpc/src/grpc_client.h (1)

93-97: Perfect‑forward the event to avoid an unnecessary move/copy

Arena::Create is called with std::move(event), which turns the forwarding reference into an rvalue but still forces a copy or move of the whole protobuf message.
You can construct the message in‑place inside the arena and perfectly forward the constructor arguments, avoiding one extra move and keeping the code generic for non‑movable types:

-    call_data->event = Arena::Create<EventT>(call_data->arena.get(),
-                                             std::move(event));
+    call_data->event = Arena::Create<EventT>(call_data->arena.get(),
+                                             std::forward<EventT>(event));

This is a small optimization but aligns with modern C++ best practices.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a99e192 and f7fbeec.

📒 Files selected for processing (1)
  • agents/grpc/src/grpc_client.h (2 hunks)

Comment thread agents/grpc/src/grpc_client.h
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: 0

🧹 Nitpick comments (2)
agents/grpc/src/grpc_client.h (2)

42-43: Consider using = default for special member functions.

The constructor and destructor are empty but use manual definition. Modern C++ practice favors = default for clearer intent and potential compiler optimizations.

-  GrpcAsyncCallData() {}
-  ~GrpcAsyncCallData() {}
+  GrpcAsyncCallData() = default;
+  ~GrpcAsyncCallData() = default;

27-44: Consider adding rule-of-five special member functions to GrpcAsyncCallData.

The class manages resources (unique_ptrs and function objects) but doesn't declare copy/move constructors and assignment operators. Consider either explicitly deleting them or properly implementing them to prevent unintended behavior.

 public:
   std::unique_ptr<google::protobuf::Arena> arena;
   ::grpc::Status grpc_status;
   std::unique_ptr<::grpc::ClientContext> grpc_context;

   std::function<bool(::grpc::Status,
                     std::unique_ptr<google::protobuf::Arena>&&,
                     const EventType&,
                     grpcagent::EventResponse*)> result_callback;

   EventType* event = nullptr;
   grpcagent::EventResponse* event_response = nullptr;

   GrpcAsyncCallData() = default;
   ~GrpcAsyncCallData() = default;
+  
+  // Disable copying because of unique_ptr members
+  GrpcAsyncCallData(const GrpcAsyncCallData&) = delete;
+  GrpcAsyncCallData& operator=(const GrpcAsyncCallData&) = delete;
+  
+  // Enable moving
+  GrpcAsyncCallData(GrpcAsyncCallData&&) = default;
+  GrpcAsyncCallData& operator=(GrpcAsyncCallData&&) = default;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f7fbeec and e534f5f.

📒 Files selected for processing (1)
  • agents/grpc/src/grpc_client.h (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: test-macOS
  • GitHub Check: coverage-linux
  • GitHub Check: build-tarball
  • GitHub Check: test-linux (ubuntu-24.04-arm)
  • GitHub Check: coverage-windows
  • GitHub Check: lint-js-and-md
🔇 Additional comments (3)
agents/grpc/src/grpc_client.h (3)

87-101: The event parameter handling looks good now.

The previous issue with dangling pointers has been fixed. The new code correctly creates a copy of the event in the arena, ensuring it outlives the asynchronous call, and proper error handling is implemented.

I also see that the noexcept specifier has been removed, addressing the concern about exceptions potentially terminating the process during allocation failures.


109-115: The callback handling looks improved.

The previous issue with memory deallocation has been fixed. The code no longer attempts to delete memory allocated by the arena.

However, there's a potential thread safety consideration:

call_data->result_callback(call_data->grpc_status,
                           std::move(call_data->arena),
                           *call_data->event,
                           call_data->event_response);

Ensure that the result_callback function is thread-safe, as it might be invoked from a different thread than the one that created it, and it's working with potentially shared data.


66-118:

Details

✅ Verification successful

The templated approach to DelegateAsyncExport is a good improvement.

This refactoring successfully applies the DRY principle by replacing multiple event-specific overloads with a single templated version. The implementation is robust and handles resource management appropriately:

  1. It creates the event in the arena to ensure it outlives the function call
  2. It properly handles error cases and returns an appropriate error code
  3. It sets up the callback with a lambda that properly manages the shared state

One thing to verify: does this templated implementation maintain backward compatibility with all existing call sites? The documentation example at lines 69-75 shows how to use it, but it would be good to confirm that all callers have been updated correctly.


🏁 Script executed:

#!/bin/bash
# Check for any remaining calls to DelegateAsyncExport that might not be updated to use the new template parameter
rg -A 3 "DelegateAsyncExport\(" --type cpp | grep -v "async_interface"

Length of output: 7427


Verified: No internal call sites require updating

A search for DelegateAsyncExport( within our agents/ directory only returned its declaration in agents/grpc/src/grpc_client.h. All external occurrences in deps/opentelemetry-cpp reference the OtlpGrpcClient::DelegateAsyncExport overloads in that module—not our new templated function—so they’re unaffected.

Backward compatibility is maintained; no further changes are needed.

@santigimeno santigimeno force-pushed the santi/dry_grpc_client branch from e534f5f to b897424 Compare April 22, 2025 20:08
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: 1

🧹 Nitpick comments (2)
agents/grpc/src/grpc_client.h (2)

27-44: Explicitly disable copying/moving of GrpcAsyncCallData
GrpcAsyncCallData owns an std::unique_ptr<Arena> and raw pointers that point into that arena.
Although the implicitly‑generated copy/move ctors are already deleted by the presence of the unique_ptr, making that fact explicit documents the intent and prevents accidental refactors that might re‑enable copying later.

   GrpcAsyncCallData() = default;
   ~GrpcAsyncCallData() = default;
+
+  GrpcAsyncCallData(const GrpcAsyncCallData&)            = delete;
+  GrpcAsyncCallData& operator=(const GrpcAsyncCallData&) = delete;
+  GrpcAsyncCallData(GrpcAsyncCallData&&)                 = delete;
+  GrpcAsyncCallData& operator=(GrpcAsyncCallData&&)      = delete;

110-115: Consider propagating the result of result_callback
result_callback returns a bool, yet the lambda ignores it.
If callers use that return value to signal retry/cleanup decisions, the information is silently lost here.
At minimum, document that the return value is ignored, or forward it to the caller by storing it in call_data->grpc_status/returning a different status code.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e534f5f and b897424.

📒 Files selected for processing (8)
  • .github/workflows/build-tarball.yml (2 hunks)
  • .github/workflows/coverage-linux-without-intl.yml (1 hunks)
  • .github/workflows/coverage-linux.yml (1 hunks)
  • .github/workflows/test-linux.yml (1 hunks)
  • .github/workflows/test-macos.yml (1 hunks)
  • agents/grpc/src/grpc_agent.cc (10 hunks)
  • agents/grpc/src/grpc_client.cc (0 hunks)
  • agents/grpc/src/grpc_client.h (2 hunks)
💤 Files with no reviewable changes (1)
  • agents/grpc/src/grpc_client.cc
✅ Files skipped from review due to trivial changes (4)
  • .github/workflows/coverage-linux.yml
  • .github/workflows/build-tarball.yml
  • .github/workflows/test-linux.yml
  • .github/workflows/test-macos.yml
🚧 Files skipped from review as they are similar to previous changes (2)
  • .github/workflows/coverage-linux-without-intl.yml
  • agents/grpc/src/grpc_agent.cc
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: lint-js-and-md
  • GitHub Check: coverage-linux-without-intl
  • GitHub Check: build-tarball
  • GitHub Check: test-macOS
  • GitHub Check: coverage-linux
  • GitHub Check: coverage-windows
  • GitHub Check: test-linux

Comment thread agents/grpc/src/grpc_client.h
@santigimeno santigimeno changed the base branch from node-v22.x-nsolid-v5.x to santi/merge_22_15_0 April 24, 2025 13:55
@santigimeno santigimeno force-pushed the santi/dry_grpc_client branch from b897424 to c3bc0ad Compare April 24, 2025 13:56
@santigimeno
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 24, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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: 0

♻️ Duplicate comments (1)
agents/grpc/src/grpc_client.h (1)

98-109: Replace ASSERT_NOT_NULL with runtime checks.

While ASSERT_NOT_NULL helps in debug builds, these assertions might be removed in release builds, potentially leading to crashes if null pointers are passed. Consider adding explicit null checks that return error codes in all build configurations.

-    ASSERT_NOT_NULL(stub);
-    ASSERT_NOT_NULL(exportFunc);
+    if (stub == nullptr || exportFunc == nullptr) {
+      return -1;
+    }
🧹 Nitpick comments (1)
agents/grpc/src/grpc_client.h (1)

83-97: Parameter type could be simplified.

The parameter EventT&& event uses a forwarding reference, but the implementation simply moves the value. Since perfect forwarding isn't needed here, consider simplifying to EventT event to improve readability and maintain the same behavior.

-    EventT&& event,
+    EventT event,
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b897424 and c3bc0ad.

📒 Files selected for processing (3)
  • agents/grpc/src/grpc_agent.cc (10 hunks)
  • agents/grpc/src/grpc_client.cc (0 hunks)
  • agents/grpc/src/grpc_client.h (3 hunks)
💤 Files with no reviewable changes (1)
  • agents/grpc/src/grpc_client.cc
🚧 Files skipped from review as they are similar to previous changes (1)
  • agents/grpc/src/grpc_agent.cc
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: test-tarball-linux
  • GitHub Check: test-linux (ubuntu-24.04-arm)
  • GitHub Check: test-macOS
  • GitHub Check: test-linux (ubuntu-24.04)
  • GitHub Check: coverage-windows
  • GitHub Check: coverage-linux
  • GitHub Check: coverage-linux-without-intl
🔇 Additional comments (5)
agents/grpc/src/grpc_client.h (5)

25-50: The template class is well-designed.

Moving the GrpcAsyncCallData template class from the implementation file to the header is appropriate for template code. The class properly manages resources, disables copying/moving, and clearly defines the lifecycle of objects.


103-106: Good use of Arena allocation.

Using Arena::Create for both event and response objects ensures they have the proper lifetime and addresses the previous dangling pointer issue. The arena is correctly passed to the callback, ensuring it remains valid until the callback completes.


72-82: Clear and helpful documentation.

The documentation with usage examples greatly improves the usability of this templated method, making it clear how to call it with different event types.


107-109: Proper allocation failure handling.

Returning -1 instead of using assert(0) is a better approach for handling allocation failures, as it allows callers to handle the error gracefully even in release builds.


114-123: Template method invocation is clear and correct.

The code properly uses the template function pointer to call the correct export method on the stub. The lambda capture and callback forwarding also look correct, with proper resource management.

@santigimeno santigimeno force-pushed the santi/merge_22_15_0 branch 2 times, most recently from 4fbc831 to e76de7a Compare April 28, 2025 09:10
Base automatically changed from santi/merge_22_15_0 to node-v22.x-nsolid-v5.x April 28, 2025 09:11
@santigimeno santigimeno force-pushed the santi/dry_grpc_client branch from c3bc0ad to 6b2db83 Compare April 28, 2025 09:31
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: 0

🧹 Nitpick comments (1)
agents/grpc/src/grpc_client.h (1)

84-97: Parameter type for event could be improved.

The function takes EventT&& event but later moves from it. It would be clearer to use either:

  1. EventT event (by value) - explicitly showing the intent to take ownership
  2. const EventT& event + copy in the implementation - if copying is preferred

The current approach works but could lead to confusion about ownership transfer.

- EventT&& event,
+ EventT event,
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c3bc0ad and 6b2db83.

📒 Files selected for processing (3)
  • agents/grpc/src/grpc_agent.cc (10 hunks)
  • agents/grpc/src/grpc_client.cc (0 hunks)
  • agents/grpc/src/grpc_client.h (3 hunks)
💤 Files with no reviewable changes (1)
  • agents/grpc/src/grpc_client.cc
🚧 Files skipped from review as they are similar to previous changes (1)
  • agents/grpc/src/grpc_agent.cc
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: lint-py
  • GitHub Check: test-linux (ubuntu-24.04-arm)
  • GitHub Check: lint-cpp
  • GitHub Check: lint-js-and-md
  • GitHub Check: test-linux (ubuntu-24.04)
  • GitHub Check: build-tarball
  • GitHub Check: build-docs
  • GitHub Check: coverage-windows
  • GitHub Check: coverage-linux
  • GitHub Check: coverage-linux-without-intl
  • GitHub Check: test-macOS
🔇 Additional comments (6)
agents/grpc/src/grpc_client.h (6)

4-4: Good addition of the assertions header.

The inclusion of "asserts-cpp/asserts.h" is appropriate for the ASSERT_NOT_NULL macros used later in the code.


18-18: LGTM: Clean addition of using directive.

The using directive for google::protobuf::Arena reduces verbosity in the code that follows.


25-50: Well-designed async call data template class.

Moving the GrpcAsyncCallData class from the source file to the header is appropriate for template visibility. The class is well-structured with:

  • Clear member variable organization
  • Proper memory ownership semantics with unique_ptr
  • Complete rule-of-five implementation (disabling copy/move operations)
  • Default constructor and destructor

This implementation properly encapsulates all the state needed for an asynchronous gRPC call.


72-82: Excellent documentation with usage example.

The function documentation clearly explains how to use the templated method and provides a concrete usage example, which is very helpful for maintainers.


98-109: Good null checks and error handling.

The implementation properly:

  1. Asserts that both stub and exportFunc are not null
  2. Creates and initializes the call data
  3. Allocates the event and response in the Arena
  4. Returns an error code when allocation fails

This addresses previous review feedback about proper error handling.


111-126: Clean implementation of async call delegation.

The implementation:

  1. Properly transfers ownership of objects
  2. Correctly captures shared_ptr to call_data in the lambda
  3. Sets up appropriate callback chaining
  4. No longer deletes Arena-allocated memory

This addresses previous concerns about object lifetime and memory management.

This commit refactors the GrpcClient::DelegateAsyncExport method to use
templates instead of having multiple overloaded implementations for each
event type.

This change significantly reduces code duplication while maintaining the
same functionality, making the codebase more maintainable and less prone
to errors when adding new event types.
@santigimeno santigimeno force-pushed the santi/dry_grpc_client branch from 6b2db83 to 43911c9 Compare April 28, 2025 10:07
Copy link
Copy Markdown
Member

@RafaelGSS RafaelGSS left a comment

Choose a reason for hiding this comment

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

RSLGTM

santigimeno added a commit that referenced this pull request Apr 29, 2025
This commit refactors the GrpcClient::DelegateAsyncExport method to use
templates instead of having multiple overloaded implementations for each
event type.

This change significantly reduces code duplication while maintaining the
same functionality, making the codebase more maintainable and less prone
to errors when adding new event types.

PR-URL: #294
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
@santigimeno
Copy link
Copy Markdown
Member Author

Landed in d0c432e

@santigimeno santigimeno deleted the santi/dry_grpc_client branch April 29, 2025 14:38
santigimeno added a commit that referenced this pull request May 1, 2025
This commit refactors the GrpcClient::DelegateAsyncExport method to use
templates instead of having multiple overloaded implementations for each
event type.

This change significantly reduces code duplication while maintaining the
same functionality, making the codebase more maintainable and less prone
to errors when adding new event types.

PR-URL: #294
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
santigimeno added a commit that referenced this pull request May 2, 2025
This commit refactors the GrpcClient::DelegateAsyncExport method to use
templates instead of having multiple overloaded implementations for each
event type.

This change significantly reduces code duplication while maintaining the
same functionality, making the codebase more maintainable and less prone
to errors when adding new event types.

PR-URL: #294
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
santigimeno added a commit that referenced this pull request May 7, 2025
This commit refactors the GrpcClient::DelegateAsyncExport method to use
templates instead of having multiple overloaded implementations for each
event type.

This change significantly reduces code duplication while maintaining the
same functionality, making the codebase more maintainable and less prone
to errors when adding new event types.

PR-URL: #294
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
santigimeno added a commit that referenced this pull request May 7, 2025
This commit refactors the GrpcClient::DelegateAsyncExport method to use
templates instead of having multiple overloaded implementations for each
event type.

This change significantly reduces code duplication while maintaining the
same functionality, making the codebase more maintainable and less prone
to errors when adding new event types.

PR-URL: #294
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
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.

2 participants