Skip to content

obj plugin: introduce registry for vendor backends - #1550

Merged
ovidiusm merged 5 commits into
ai-dynamo:mainfrom
scality:plugin_obj_registry
Jun 5, 2026
Merged

ovidiusm merged 5 commits into
ai-dynamo:mainfrom
scality:plugin_obj_registry

Conversation

@oliviergaraud

@oliviergaraud oliviergaraud commented Apr 17, 2026 •

Copy link
Copy Markdown
Contributor

What?

Implement a self-registration pattern for accelerated OBJ engines.

Replace the #ifdef ladder in obj_backend.cpp with a self-registration
pattern for accelerated OBJ engines (S3Accel, Dell ObjectScale).
Extract mock S3 client classes into reusable headers and mirror the registry pattern on the test side.

Why?

To handle // TODO: Consider a registration pattern as more vendor engines are added.

Adding a new vendor engine required modifying obj_backend.cpp (two factory overloads, #ifdef guards, includes), which was error-prone and can caused merge conflicts when multiple engines were developed in parallel.

With the registry, new engines are self-contained: implement, add a static registrar, update meson.build

How?

  • New objAccelEngineRegistry singleton maps engine type strings to factory
    lambdas; objAccelEngineRegistrar RAII helper handles static-init registration from each engine's .cpp.
  • obj_backend.cpp delegates to the registry when accelerated=true, removing all vendor-specific code.
  • Test-side mockClientRegistry mirrors the pattern for mock S3 client creation.
  • README updated to reflect the new workflow.

Open with Devin

Summary by CodeRabbit

  • New Features

    • Config now supports enabling acceleration and selecting an accelerated engine type.
  • Refactor

    • Accelerated engines self-register; selection flow and error reporting simplified.
  • Build

    • Plugin build/linking adjusted to include acceleration registry and refine linking behavior.
  • Tests

    • Unit tests centralize mock-client registration and add deterministic mocks for accelerated backends.
  • Documentation

    • Backend docs updated with self-registration guidance and new acceleration parameters.

@copy-pr-bot

copy-pr-bot Bot commented Apr 17, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions

Copy link
Copy Markdown

👋 Hi oliviergaraud! Thank you for contributing to ai-dynamo/nixl.

Your PR reviewers will review your contribution then trigger the CI to test your changes.

🚀

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

@coderabbitai

coderabbitai Bot commented Apr 17, 2026 •

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Add a thread-safe singleton registry for accelerated object-engine implementations; engines self-register via a static registrar. The OBJ backend parses an accelerated "type" custom param and delegates accelerated engine creation to the registry. Tests gain a mock-client registry and shared mock S3/Dell mock implementations.

Changes

Cohort / File(s) Summary
Registry Infrastructure
src/plugins/obj/obj_engine_registry.h, src/plugins/obj/obj_engine_registry.cpp
Add objAccelEngineRegistry singleton and objAccelEngineRegistrar; store type→factory entries (plain and with S3 clients), mutex-protected lookup, duplicate-warning, and two create(...) overloads.
Backend Integration & Docs
src/plugins/obj/obj_backend.cpp, src/plugins/obj/README.md
Remove prior compile-time engine branching; read "type" from nixl_b_params_t::customParams and delegate accelerated creation to objAccelEngineRegistry::instance().create(...); add try/catch around registry create and update README to require self-registration and guard cuobj-specific code.
Engine Registrations
src/plugins/obj/s3_accel/engine_impl.cpp, src/plugins/obj/s3_accel/dell/engine_impl.cpp
Include registry header and add file-scope static objAccelEngineRegistrar instances registering default ("") and "dell" accelerator factories (both plain and client-injected constructors).
Build & Tests Build Config
src/plugins/obj/meson.build, test/gtest/unit/obj/meson.build
Add registry source files to OBJ plugin build, refactor plugin dependency/compile-arg setup, adjust obj_backend_interface dependency declaration for static plugins, and conditionally include mock test source when CUOBJ dep found.
Utils Cleanup
src/utils/object/engine_utils.h
Remove inline helper isDellOBSRequested(...).
Test Infrastructure & Mocks
test/gtest/unit/obj/mock_client_registry.h, test/gtest/unit/obj/mock_s3_client.h, test/gtest/unit/obj/mock_dell_s3_client.cpp, test/gtest/unit/obj/obj.cpp
Add mockClientRegistry and mockClientRegistrar; introduce shared mockS3Client and mockDellS3Client implementations; update obj.cpp to obtain mocks via registry by type, throwing if a non-empty type has no registered mock and falling back to default otherwise.

Sequence Diagram(s)

sequenceDiagram
    participant Backend as Backend
    participant Registry as objAccelEngineRegistry
    participant Factory as EngineFactory
    participant Engine as nixlObjEngineImpl
    participant S3 as iS3Client

    Backend->>Registry: create(type, init_params[, s3_client, s3_client_crt])
    Registry->>Registry: lookupOrThrow(type)
    alt factory requires clients
        Registry->>Factory: createWithClients(init_params, s3_client, s3_client_crt)
        Factory->>Engine: construct(engine with injected S3 clients)
    else factory simple
        Registry->>Factory: create(init_params)
        Factory->>Engine: construct(engine)
    end
    Engine-->>Backend: return unique_ptr<nixlObjEngineImpl>
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰
I hop where registrars softly bind,
Types tuck into a threaded mind,
Factories bloom without guarded calls,
Backend asks, the registry fills the halls,
Tests mock, I nibble carrots and find.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.90% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'obj plugin: introduce registry for vendor backends' accurately and concisely summarizes the main change—introducing a registry pattern for vendor OBJ engines.
Description check ✅ Passed The PR description follows the template with clear What/Why/How sections that comprehensively explain the self-registration pattern implementation, motivation, and technical approach.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Caution

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

⚠️ Outside diff range comments (2)
src/plugins/obj/meson.build (1)

41-74: 🧹 Nitpick | 🔵 Trivial

compile_flags is applied only in the static build path.

Line 65 uses compile_defs + compile_flags while line 74 uses compile_defs + ['-fPIC'] and drops compile_flags. Today compile_flags is empty, so this is inert, but the asymmetry will silently diverge the two build configurations as soon as something is added to it.

♻️ Suggested symmetry
-        cpp_args: compile_defs + ['-fPIC'],
+        cpp_args: compile_defs + compile_flags + ['-fPIC'],
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/plugins/obj/meson.build` around lines 41 - 74, The shared-library branch
for obj_backend_lib omits compile_flags while the static branch uses
compile_defs + compile_flags, which will diverge configurations when
compile_flags becomes non-empty; update the shared_library call in the else
branch so its cpp_args mirrors the static branch plus position-independent code
(e.g., use cpp_args: compile_defs + compile_flags + ['-fPIC'] or prepend
compile_flags into the existing list), making sure the symbol names referenced
are compile_flags and obj_backend_lib (and the static_plugins conditional) so
both static and shared builds receive the same compile_flags.
src/plugins/obj/obj_backend.cpp (1)

42-59: ⚠️ Potential issue | 🟠 Major

Unguarded registry exceptions will crash the OBJ plugin constructor — wrap in try/catch or return error status.

objAccelEngineRegistry::create(...) throws std::runtime_error when the requested type isn't registered (see src/plugins/obj/obj_engine_registry.cpp lines 26–54). These calls in createObjEngineImpl (lines 43–44 and 56–59) are unguarded; since createObjEngineImpl runs from nixlObjEngine's member initializer (lines 68–69 and 74–75), exceptions escape the constructor. The plugin framework's createEngine at nixl_agent.cpp:343 does not catch them, so a user passing a misspelled or uncompiled accelerated engine type will cause an uncaught std::runtime_error to propagate up the stack.

This is a breaking change from the previous #ifdef flow (which fell back silently). Compare to src/plugins/gpunetio/gpunetio_plugin.cpp:25–28, which wraps its constructor in try/catch. Either:

  • Catch exceptions here and return nullptr (letting the caller surface NIXL_ERR_BACKEND), or
  • Confirm the agent/application framework always wraps createBackend in try/catch (as seen in test/unit/plugins/gusli/nixl_gusli_test.cpp:429–434).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/plugins/obj/obj_backend.cpp` around lines 42 - 59, The calls to
objAccelEngineRegistry::instance().create(...) inside createObjEngineImpl
(guarded by isAcceleratedRequested and using getAccelType) can throw
std::runtime_error and are currently unguarded; wrap each registry create call
in a try/catch that catches std::exception (or std::runtime_error) and on error
log the exception and return nullptr (or otherwise return an error sentinel) so
exceptions do not escape the nixlObjEngine constructor; ensure both overloads of
createObjEngineImpl handle the exception the same way.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/plugins/obj/obj_backend.cpp`:
- Around line 29-38: Change the helper getAccelType to accept a const pointer
since it only reads custom_params: update the function signature to take const
nixl_b_params_t *custom_params and adjust any internal usage to respect
constness (e.g., iterator types or find calls) so the function compiles with
const-qualified arguments; ensure callers of getAccelType still match or are
updated if necessary.

In `@src/plugins/obj/obj_engine_registry.cpp`:
- Around line 17-19: The add() method in objAccelEngineRegistry silently
overwrites existing entries in entries_ causing non-deterministic static-init
collisions; update objAccelEngineRegistry::add to detect duplicates by using
entries_.emplace(type, std::move(entry)) and check the emplace return value, and
if insertion fails either assert or emit a warning/error (e.g., via the
registry's logging mechanism) that the given type was already registered
(include the type name and possibly existing entry info) so duplicate
registrations are detected instead of overwritten.
- Around line 10-54: The file fails the project's clang-format check; reformat
the objAccelEngineRegistry implementations (methods:
objAccelEngineRegistry::instance, add, has, and both create overloads) using the
project's configured clang-format-19 and commit the updated formatting so the
signatures, braces, indentation and line breaks match the project's style; run
clang-format-19 on this file (or the repo) and replace the current contents with
the formatted output before pushing.
- Around line 26-54: The two objAccelEngineRegistry::create overloads duplicate
the same entries_ lookup and error handling; add a private helper method (e.g.,
objAccelEngineRegistry::lookupOrThrow(const std::string& type) const) that finds
the entry in entries_ and throws the existing "not compiled"/runtime_error
messages when missing or when type is empty, then change both create(const
std::string&, const nixlBackendInitParams*) and create(const std::string&, const
nixlBackendInitParams*, std::shared_ptr<iS3Client>, std::shared_ptr<iS3Client>)
to call lookupOrThrow(type) and then invoke entry.create(...) or
entry.createWithClients(...), respectively, to eliminate the duplicated logic
while keeping the same behavior and error texts.

In `@src/plugins/obj/obj_engine_registry.h`:
- Around line 18-57: The header fails clang-format checks; reformat this file
using clang-format-19 to match project style so the typedefs and structs
(obj_accel_create_fn_t, obj_accel_create_with_clients_fn_t,
objAccelEngineEntry), the class objAccelEngineRegistry (instance(), add(),
has(), create() overloads, entries_), and the objAccelEngineRegistrar
constructor are properly indented/wrapped; run clang-format-19 on the file and
commit the resulting changes.
- Around line 31-50: The registry is a mutable global singleton
(objAccelEngineRegistry) and currently accesses entries_ without
synchronization; either document the "register during static init, read at
runtime" contract or make the class thread-safe—preferably add a std::mutex
member (e.g., mutex_) and take a std::lock_guard<std::mutex> in add(), has(),
and both create() overloads to protect accesses to entries_; update the header
to declare the mutex_ and update the implementation of add/has/create to lock it
around reads/writes to entries_ (or alternatively add a brief comment on the
static-init-only requirement and an assert/seal to enforce it).
- Around line 6-7: The header guard macro in obj_engine_registry.h uses
OBJ_ENGINE_REGISTRY_H which doesn't follow the repo convention; change both
occurrences of the guard (the `#ifndef/`#define and the corresponding `#endif`
comment if present) to the repo-standard macro
NIXL_SRC_PLUGINS_OBJ_OBJ_ENGINE_REGISTRY_H so the guard is upper-snake-case
derived from the full path; update occurrences referencing OBJ_ENGINE_REGISTRY_H
in this file (and matching `#endif`) to the new NIXL_... name to ensure uniqueness
and style compliance.

In `@src/plugins/obj/s3_accel/dell/engine_impl.cpp`:
- Around line 18-28: The registrar declaration reg_dell using
objAccelEngineRegistrar and the lambda factories for S3DellObsObjEngineImpl is
misformatted and placed outside the file-local anonymous namespace; run
clang-format-19 to fix formatting and move the static objAccelEngineRegistrar
reg_dell(...) declaration into the existing anonymous namespace (where the other
TU-local helpers live) so the symbol is file-local and grouped with
S3DellObsObjEngineImpl helpers.

In `@src/plugins/obj/s3_accel/engine_impl.cpp`:
- Around line 10-19: Run clang-format-19 on this file to fix the style diffs,
and add a short comment explaining the empty-string registration key used when
constructing reg_s3_accel (e.g., that "" matches the default returned by
getAccelType() when no "type" is set in custom params). Locate the static
registrar symbol reg_s3_accel and the constructor usages of S3AccelObjEngineImpl
in this block and insert the explanatory comment immediately above the registrar
declaration; then reformat the file with clang-format-19.

In `@test/gtest/unit/obj/mock_client_registry.h`:
- Around line 19-36: The header formatting for class mockClientRegistry (methods
instance, add, create) does not match project style; run clang-format-19 on
test/gtest/unit/obj/mock_client_registry.h to reformat the class and its methods
(instance(), add(), create()), then stage the updated file so CI passes the
Clang Format Check.
- Around line 6-7: The header guard macro
TEST_GTEST_UNIT_OBJ_MOCK_CLIENT_REGISTRY_H lacks the required NIXL_ prefix;
update the guard to NIXL_TEST_GTEST_UNIT_OBJ_MOCK_CLIENT_REGISTRY_H in both the
`#ifndef/`#define and corresponding `#endif` comment, ensuring the macro follows the
project's upper-snake-case rule derived from the header's repo-relative path and
that all occurrences (including any include guards or comments referencing it)
are updated to match.

In `@test/gtest/unit/obj/mock_dell_s3_client.cpp`:
- Around line 57-59: The file fails clang-format CI around the static registrar
definition; run clang-format-19 on test/gtest/unit/obj/mock_dell_s3_client.cpp
to fix spacing/linebreaks for the static variable reg_dell and its initializer
(symbols: reg_dell, mockClientRegistrar, mockDellS3Client). Reformat the file
with clang-format-19 and commit the resulting changes so the registrar
definition matches the project's style.

In `@test/gtest/unit/obj/mock_s3_client.h`:
- Around line 29-34: The ctor mockS3Client and setExecutor currently do a
std::dynamic_pointer_cast to asioThreadPoolExecutor and silently store nullptr
in executor_, which later causes execAsync() to crash; change both places (the
mockS3Client constructor and setExecutor) to check the result of the
dynamic_pointer_cast and fail fast if it returns nullptr (e.g., use an assertion
or throw a clear runtime_error) so tests immediately surface passing a
non-asioThreadPoolExecutor rather than crashing later in execAsync().
- Around line 78-85: The execAsync() implementation dereferences executor_
without checking for null; update execAsync() (which iterates pendingCallbacks_
and calls executor_->Submit(...) and executor_->waitUntilIdle()) to guard
against a null executor_ (set via setExecutor()); either throw a clear
std::runtime_error or assert with a descriptive message when executor_ is null,
or skip submitting callbacks and only clear pendingCallbacks_ and return when
executor_ is null—choose one of these behaviors and apply it consistently so
execAsync() no longer segfaults when the parameterless mockS3Client constructor
is used and setExecutor() was never called.

In `@test/gtest/unit/obj/obj.cpp`:
- Around line 65-70: The test silently falls back to base mock when
mockClientRegistry::instance().create(type) returns nullptr for a non-empty
customParams_["type"], masking missing registrar/link issues; update the fixture
to check the local variable type and, if type is non-empty and
mockClientRegistry::instance().create(type) returns nullptr, fail the test with
a clear assertion/error (mentioning the missing registered mock for that type)
instead of silently using mockS3Client_, otherwise allow the existing fallback
when type is empty; modify the code around the create(type) call and the
mockS3Client_ assignment and ensure objEngine_ construction remains unchanged.

---

Outside diff comments:
In `@src/plugins/obj/meson.build`:
- Around line 41-74: The shared-library branch for obj_backend_lib omits
compile_flags while the static branch uses compile_defs + compile_flags, which
will diverge configurations when compile_flags becomes non-empty; update the
shared_library call in the else branch so its cpp_args mirrors the static branch
plus position-independent code (e.g., use cpp_args: compile_defs + compile_flags
+ ['-fPIC'] or prepend compile_flags into the existing list), making sure the
symbol names referenced are compile_flags and obj_backend_lib (and the
static_plugins conditional) so both static and shared builds receive the same
compile_flags.

In `@src/plugins/obj/obj_backend.cpp`:
- Around line 42-59: The calls to objAccelEngineRegistry::instance().create(...)
inside createObjEngineImpl (guarded by isAcceleratedRequested and using
getAccelType) can throw std::runtime_error and are currently unguarded; wrap
each registry create call in a try/catch that catches std::exception (or
std::runtime_error) and on error log the exception and return nullptr (or
otherwise return an error sentinel) so exceptions do not escape the
nixlObjEngine constructor; ensure both overloads of createObjEngineImpl handle
the exception the same way.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 43c5ad3e-6753-427a-988a-741c804a1d1e

📥 Commits

Reviewing files that changed from the base of the PR and between 278e819 and 46d6e19.

📒 Files selected for processing (13)
  • src/plugins/obj/README.md
  • src/plugins/obj/meson.build
  • src/plugins/obj/obj_backend.cpp
  • src/plugins/obj/obj_engine_registry.cpp
  • src/plugins/obj/obj_engine_registry.h
  • src/plugins/obj/s3_accel/dell/engine_impl.cpp
  • src/plugins/obj/s3_accel/engine_impl.cpp
  • src/utils/object/engine_utils.h
  • test/gtest/unit/obj/meson.build
  • test/gtest/unit/obj/mock_client_registry.h
  • test/gtest/unit/obj/mock_dell_s3_client.cpp
  • test/gtest/unit/obj/mock_s3_client.h
  • test/gtest/unit/obj/obj.cpp
💤 Files with no reviewable changes (1)
  • src/utils/object/engine_utils.h

Comment thread src/plugins/obj/obj_backend.cpp
Comment thread src/plugins/obj/obj_engine_registry.cpp
Comment thread src/plugins/obj/obj_engine_registry.cpp
Comment thread src/plugins/obj/obj_engine_registry.cpp Outdated
Comment thread src/plugins/obj/obj_engine_registry.h Outdated
Comment thread test/gtest/unit/obj/mock_client_registry.h
Comment thread test/gtest/unit/obj/mock_dell_s3_client.cpp Outdated
Comment thread test/gtest/unit/obj/mock_s3_client.h Outdated
Comment thread test/gtest/unit/obj/mock_s3_client.h Outdated
Comment thread test/gtest/unit/obj/obj.cpp Outdated
devin-ai-integration[bot]

This comment was marked as resolved.

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

Caution

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

⚠️ Outside diff range comments (1)
src/plugins/obj/README.md (1)

358-358: ⚠️ Potential issue | 🟡 Minor

Example vendor headers use #pragma once, contradicting project style.

The sample client.h (line 358) and engine_impl.h (line 387) use #pragma once, but NIXL C++ style mandates traditional #ifndef/#define header guards. Since this README is the onboarding reference new vendor authors will copy verbatim, these snippets will seed non-compliant code.

As per coding guidelines: "use traditional #ifndef/#define header guards (no #pragma once) with an upper-snake-case name derived from the file path".

📝 Proposed fix
 **client.h**
 ```cpp
-#pragma once
+#ifndef NIXL_PLUGINS_OBJ_S3_ACCEL_VENDOR_NAME_CLIENT_H
+#define NIXL_PLUGINS_OBJ_S3_ACCEL_VENDOR_NAME_CLIENT_H
 `#include` "s3_accel/client.h"
 …
+#endif // NIXL_PLUGINS_OBJ_S3_ACCEL_VENDOR_NAME_CLIENT_H

engine_impl.h

-#pragma once
+#ifndef NIXL_PLUGINS_OBJ_S3_ACCEL_VENDOR_NAME_ENGINE_IMPL_H
+#define NIXL_PLUGINS_OBJ_S3_ACCEL_VENDOR_NAME_ENGINE_IMPL_H
`#include` "s3_accel/engine_impl.h"
…
+#endif // NIXL_PLUGINS_OBJ_S3_ACCEL_VENDOR_NAME_ENGINE_IMPL_H
</details>


Also applies to: 387-387

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @src/plugins/obj/README.md at line 358, The README examples use "#pragma
once" which violates NIXL C++ style; replace the pragma in the vendor sample
headers (client.h and engine_impl.h) with traditional include guards: add an
#ifndef/#define pair at the top and a matching #endif at the bottom using an
upper-snake-case name derived from the file path (use
NIXL_PLUGINS_OBJ_S3_ACCEL_VENDOR_NAME_CLIENT_H for client.h and
NIXL_PLUGINS_OBJ_S3_ACCEL_VENDOR_NAME_ENGINE_IMPL_H for engine_impl.h), and keep
all existing includes and content between the guard macros.


</details>

</blockquote></details>

</blockquote></details>
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/plugins/obj/obj_backend.cpp`:
- Around line 43-51: Extract the duplicated try/catch/log/rethrow into a small
helper function (e.g., createAccelEngine) and use it from both
createObjEngineImpl overloads: have createAccelEngine accept the accel type and
init_params (or just init_params and call getAccelType inside) and perform
objAccelEngineRegistry::instance().create(... ) inside a single try block, catch
const std::exception& e, call NIXL_ERROR with the error message, then rethrow;
replace the two duplicated try/catch blocks in createObjEngineImpl with a single
call to createAccelEngine to centralize logging and error handling.

In `@src/plugins/obj/obj_engine_registry.cpp`:
- Line 19: The local std::lock_guard usages should be declared const for
const-correctness: replace occurrences of "std::lock_guard<std::mutex>
lock(mutex_);" with "const std::lock_guard<std::mutex> lock(mutex_);" (apply the
same change to the other two lock declarations in the file) so all local
lock_guard locals (e.g., the variables named lock that protect mutex_) are
const-qualified.
- Around line 33-44: lookupOrThrow currently returns a const reference to an
element from the unordered_map entries_ after releasing mutex_, which is unsafe
because concurrent add() can rehash and invalidate the reference; modify
objAccelEngineRegistry::lookupOrThrow to return objAccelEngineEntry by value
instead (copy the found entry while holding mutex_ and return the copy) or, if
you prefer keeping references, perform the factory invocation (e.g., call
.create()/.createWithClients()) while still holding mutex_ to avoid returning an
invalid reference; update the function signature and implementation in
objAccelEngineRegistry accordingly.

In `@src/plugins/obj/obj_engine_registry.h`:
- Around line 19-24: The two type aliases obj_accel_create_fn_t and
obj_accel_create_with_clients_fn_t violate the project's lower camelCase type
naming; rename them to objAccelCreateFn and objAccelCreateWithClientsFn
respectively, preserving their signatures (returning
std::unique_ptr<nixlObjEngineImpl> and taking const nixlBackendInitParams* and
optionally std::shared_ptr<iS3Client> twice); update all local references
(including in objAccelEngineEntry and objAccelEngineRegistry) and any forward
declarations or headers that use these aliases so builds and signatures remain
consistent.

In `@src/plugins/obj/README.md`:
- Line 346: The README line advising to guard cuobjclient-specific code should
use the idiomatic preprocessor forms; update the example `#if defined
HAVE_CUOBJ_CLIENT` to either `#ifdef HAVE_CUOBJ_CLIENT` for the simple case or
`#if defined(HAVE_CUOBJ_CLIENT)` when combined with other conditions so vendor
authors follow the canonical style when guarding code with HAVE_CUOBJ_CLIENT.
- Around line 456-468: The README example shows registrar lambdas using the
fixed factory signature (params, s3, s3_crt) via objAccelEngineRegistrar, but
step 2 and the VendorObjEngineImpl constructors are inconsistent (the documented
second ctor takes (const nixlBackendInitParams*, std::shared_ptr<iS3Client>)
while the registrar factory supplies s3_crt); update the docs to explicitly
state that accel engines and VendorObjEngineImpl typically ignore the CRT client
(iS3Client s3_crt), clarify that the registrar's createWithClients factory must
accept (p, s3, s3_crt) even if s3_crt is unused, and either align the example
constructor signature with the real VendorObjEngineImpl constructors or add a
note explaining why the ctor drops s3_crt so copy-pasters know to accept but not
use s3_crt.

In `@src/plugins/obj/s3_accel/engine_impl.cpp`:
- Around line 12-18: The registrar reg_s3_accel (which constructs
S3AccelObjEngineImpl using nixlBackendInitParams and iS3Client) is currently
declared as a file-scope static; move its declaration into an anonymous
namespace to match the sibling file and project style: remove the file-scope
static placement and wrap the reg_s3_accel definition inside namespace { ... }
so it remains internal linkage but follows the anonymous-namespace convention.

In `@test/gtest/unit/obj/mock_dell_s3_client.cpp`:
- Around line 20-32: The parameters key, data_ptr, data_len, and offset in
putObjectRdmaAsync (and key in getObjectRdmaAsync) are unused; mark them as
[[maybe_unused]] (or remove their names) to match the constructor-style hygiene
in mock_s3_client.h. Update the function signatures for putObjectRdmaAsync and
getObjectRdmaAsync to annotate the unused parameters with [[maybe_unused]] (or
drop the identifier) so the compiler no longer warns about unused parameters
while preserving the existing behavior and callback logic.
- Around line 10-59: Move the mockDellS3Client class and the reg_dell registrar
into a TU-local anonymous namespace instead of relying on static linkage; locate
the declarations of mockDellS3Client and the static mockClientRegistrar reg_dell
and wrap them in `namespace { ... }` so both the class and the registrar become
internal to the translation unit, mirroring the pattern used by
s3_accel/dell/engine_impl.cpp.

In `@test/gtest/unit/obj/mock_s3_client.h`:
- Around line 53-59: The parameter list for putObjectAsync (and any similar
mocks like getObjectAsync) declares key, data_ptr, data_len, offset but never
uses them, which can trigger -Wunused-parameter; update the function signatures
for putObjectAsync (and getObjectAsync if present) to mark unused parameters
with [[maybe_unused]] (e.g., [[maybe_unused]] std::string_view key,
[[maybe_unused]] uintptr_t data_ptr, etc.) so the compiler won’t warn, leaving
the existing pendingCallbacks_ lambda and behavior unchanged.
- Around line 6-7: The header guard macro in mock_s3_client.h uses
TEST_GTEST_UNIT_OBJ_MOCK_S3_CLIENT_H which doesn't follow the repo convention;
update both occurrences of the guard (the `#ifndef` and the corresponding `#define`
for mock_s3_client.h) to the canonical form
NIXL_TEST_GTEST_UNIT_OBJ_MOCK_S3_CLIENT_H and ensure the trailing `#endif` (in the
same file) optionally comments the macro name for clarity; locate the macro by
the existing symbol TEST_GTEST_UNIT_OBJ_MOCK_S3_CLIENT_H and replace it with
NIXL_TEST_GTEST_UNIT_OBJ_MOCK_S3_CLIENT_H.

---

Outside diff comments:
In `@src/plugins/obj/README.md`:
- Line 358: The README examples use "#pragma once" which violates NIXL C++
style; replace the pragma in the vendor sample headers (client.h and
engine_impl.h) with traditional include guards: add an `#ifndef/`#define pair at
the top and a matching `#endif` at the bottom using an upper-snake-case name
derived from the file path (use NIXL_PLUGINS_OBJ_S3_ACCEL_VENDOR_NAME_CLIENT_H
for client.h and NIXL_PLUGINS_OBJ_S3_ACCEL_VENDOR_NAME_ENGINE_IMPL_H for
engine_impl.h), and keep all existing includes and content between the guard
macros.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 705ef14e-f80e-48fb-9444-65b44e2072c7

📥 Commits

Reviewing files that changed from the base of the PR and between 46d6e19 and b95cef2.

📒 Files selected for processing (13)
  • src/plugins/obj/README.md
  • src/plugins/obj/meson.build
  • src/plugins/obj/obj_backend.cpp
  • src/plugins/obj/obj_engine_registry.cpp
  • src/plugins/obj/obj_engine_registry.h
  • src/plugins/obj/s3_accel/dell/engine_impl.cpp
  • src/plugins/obj/s3_accel/engine_impl.cpp
  • src/utils/object/engine_utils.h
  • test/gtest/unit/obj/meson.build
  • test/gtest/unit/obj/mock_client_registry.h
  • test/gtest/unit/obj/mock_dell_s3_client.cpp
  • test/gtest/unit/obj/mock_s3_client.h
  • test/gtest/unit/obj/obj.cpp
💤 Files with no reviewable changes (1)
  • src/utils/object/engine_utils.h

Comment thread src/plugins/obj/obj_backend.cpp Outdated
Comment thread src/plugins/obj/obj_engine_registry.cpp Outdated
Comment thread src/plugins/obj/obj_engine_registry.cpp Outdated
Comment thread src/plugins/obj/obj_engine_registry.h
Comment thread src/plugins/obj/README.md Outdated
Comment thread src/plugins/obj/s3_accel/engine_impl.cpp
Comment thread test/gtest/unit/obj/mock_dell_s3_client.cpp
Comment thread test/gtest/unit/obj/mock_dell_s3_client.cpp Outdated
Comment thread test/gtest/unit/obj/mock_s3_client.h Outdated
Comment thread test/gtest/unit/obj/mock_s3_client.h Outdated
devin-ai-integration[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

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

♻️ Duplicate comments (4)
test/gtest/unit/obj/mock_dell_s3_client.cpp (2)

12-57: 🛠️ Refactor suggestion | 🟠 Major

Move TU-local mockDellS3Client and reg_dell into an anonymous namespace.

Both symbols are strictly TU-local test helpers. The production-side registrar in src/plugins/obj/s3_accel/dell/engine_impl.cpp already uses an anonymous namespace; mirror that here instead of relying on static linkage on reg_dell and giving the class external linkage.

♻️ Proposed change
 namespace gtest::obj {
+namespace {
 
 class mockDellS3Client : public mockS3Client, public iDellS3RdmaClient {
     ...
 };
 
-static mockClientRegistrar reg_dell("dell", []() { return std::make_shared<mockDellS3Client>(); });
+mockClientRegistrar reg_dell("dell", []() { return std::make_shared<mockDellS3Client>(); });
 
+} // namespace
 } // namespace gtest::obj
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/gtest/unit/obj/mock_dell_s3_client.cpp` around lines 12 - 57, The
TU-local test helpers mockDellS3Client and reg_dell should be placed in an
anonymous namespace to give them internal linkage; wrap the mockDellS3Client
class definition and the reg_dell registration inside namespace { ... } and
remove reliance on file-scope static for reg_dell (keep the registrar creation
but move it inside the anonymous namespace) so both symbols become TU-local just
like the production registrar in engine_impl.cpp.

20-40: 🧹 Nitpick | 🔵 Trivial

Mark unused parameters [[maybe_unused]].

key in both overrides, and data_ptr/data_len/offset in putObjectRdmaAsync, are unused. Annotate them for consistency with the nixl_b_params_t *custom_params pattern used at line 16 and to keep -Wunused-parameter-clean builds.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/gtest/unit/obj/mock_dell_s3_client.cpp` around lines 20 - 40, The
overrides putObjectRdmaAsync and getObjectRdmaAsync declare parameters that are
not used; mark the unused parameters with the [[maybe_unused]] attribute (e.g.,
std::string_view key, uintptr_t data_ptr, size_t data_len, size_t offset,
std::string_view rdma_desc as appropriate) to suppress -Wunused-parameter
warnings and match the existing pattern used for nixl_b_params_t *custom_params;
update the parameter declarations in the putObjectRdmaAsync and
getObjectRdmaAsync method signatures accordingly while leaving callback usage
unchanged.
src/plugins/obj/obj_engine_registry.h (1)

19-24: 🧹 Nitpick | 🔵 Trivial

Type aliases still use snake_case + _t suffix.

obj_accel_create_fn_t and obj_accel_create_with_clients_fn_t remain inconsistent with surrounding objAccelEngineEntry / objAccelEngineRegistry / objAccelEngineRegistrar camelCase naming. Consider objAccelCreateFn and objAccelCreateWithClientsFn.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/plugins/obj/obj_engine_registry.h` around lines 19 - 24, Rename the
snake_case `_t` typedefs to camelCase to match surrounding symbols: change
obj_accel_create_fn_t to objAccelCreateFn and obj_accel_create_with_clients_fn_t
to objAccelCreateWithClientsFn; update the type definitions in
obj_engine_registry.h (the std::function signatures returning
std::unique_ptr<nixlObjEngineImpl>) and then update every usage/forward
declaration/reference (e.g., in objAccelEngineEntry, objAccelEngineRegistry,
objAccelEngineRegistrar and any factory/registration code) to use the new names
so identifiers remain consistent across the codebase.
test/gtest/unit/obj/mock_s3_client.h (1)

52-66: 🧹 Nitpick | 🔵 Trivial

Mark unused parameters in putObjectAsync / getObjectAsync as [[maybe_unused]].

putObjectAsync never uses key, data_ptr, data_len, or offset; getObjectAsync never uses key. Annotate them to match the constructor style on line 30 and avoid -Wunused-parameter regressions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/gtest/unit/obj/mock_s3_client.h` around lines 52 - 66, Annotate unused
function parameters with [[maybe_unused]] to avoid -Wunused-parameter warnings:
update the signatures of putObjectAsync (mark key, data_ptr, data_len, offset as
[[maybe_unused]]) and getObjectAsync (mark key as [[maybe_unused]]), matching
the constructor style used earlier; keep the body logic unchanged (retaining
pendingCallbacks_ push in putObjectAsync and existing getObjectAsync
implementation). Ensure only the parameter declarations change so callers and
overrides remain compatible.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/plugins/obj/obj_engine_registry.h`:
- Around line 19-24: Rename the snake_case `_t` typedefs to camelCase to match
surrounding symbols: change obj_accel_create_fn_t to objAccelCreateFn and
obj_accel_create_with_clients_fn_t to objAccelCreateWithClientsFn; update the
type definitions in obj_engine_registry.h (the std::function signatures
returning std::unique_ptr<nixlObjEngineImpl>) and then update every
usage/forward declaration/reference (e.g., in objAccelEngineEntry,
objAccelEngineRegistry, objAccelEngineRegistrar and any factory/registration
code) to use the new names so identifiers remain consistent across the codebase.

In `@test/gtest/unit/obj/mock_dell_s3_client.cpp`:
- Around line 12-57: The TU-local test helpers mockDellS3Client and reg_dell
should be placed in an anonymous namespace to give them internal linkage; wrap
the mockDellS3Client class definition and the reg_dell registration inside
namespace { ... } and remove reliance on file-scope static for reg_dell (keep
the registrar creation but move it inside the anonymous namespace) so both
symbols become TU-local just like the production registrar in engine_impl.cpp.
- Around line 20-40: The overrides putObjectRdmaAsync and getObjectRdmaAsync
declare parameters that are not used; mark the unused parameters with the
[[maybe_unused]] attribute (e.g., std::string_view key, uintptr_t data_ptr,
size_t data_len, size_t offset, std::string_view rdma_desc as appropriate) to
suppress -Wunused-parameter warnings and match the existing pattern used for
nixl_b_params_t *custom_params; update the parameter declarations in the
putObjectRdmaAsync and getObjectRdmaAsync method signatures accordingly while
leaving callback usage unchanged.

In `@test/gtest/unit/obj/mock_s3_client.h`:
- Around line 52-66: Annotate unused function parameters with [[maybe_unused]]
to avoid -Wunused-parameter warnings: update the signatures of putObjectAsync
(mark key, data_ptr, data_len, offset as [[maybe_unused]]) and getObjectAsync
(mark key as [[maybe_unused]]), matching the constructor style used earlier;
keep the body logic unchanged (retaining pendingCallbacks_ push in
putObjectAsync and existing getObjectAsync implementation). Ensure only the
parameter declarations change so callers and overrides remain compatible.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7fec83b7-b1bb-48b9-82a9-e221459cc4e1

📥 Commits

Reviewing files that changed from the base of the PR and between 3219007 and e76d5d2.

📒 Files selected for processing (13)
  • src/plugins/obj/README.md
  • src/plugins/obj/meson.build
  • src/plugins/obj/obj_backend.cpp
  • src/plugins/obj/obj_engine_registry.cpp
  • src/plugins/obj/obj_engine_registry.h
  • src/plugins/obj/s3_accel/dell/engine_impl.cpp
  • src/plugins/obj/s3_accel/engine_impl.cpp
  • src/utils/object/engine_utils.h
  • test/gtest/unit/obj/meson.build
  • test/gtest/unit/obj/mock_client_registry.h
  • test/gtest/unit/obj/mock_dell_s3_client.cpp
  • test/gtest/unit/obj/mock_s3_client.h
  • test/gtest/unit/obj/obj.cpp
💤 Files with no reviewable changes (1)
  • src/utils/object/engine_utils.h

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

♻️ Duplicate comments (2)
src/plugins/obj/obj_engine_registry.h (1)

19-28: 🧹 Nitpick | 🔵 Trivial

Rename the factory aliases to lowerCamelCase.

obj_accel_create_fn_t and obj_accel_create_with_clients_fn_t still violate the repo type-naming convention. Prefer names like objAccelCreateFn and objAccelCreateWithClientsFn, then update their uses in objAccelEngineEntry and objAccelEngineRegistrar. As per coding guidelines: “Use lowerCamelCase for types/functions and snake_case for variables/locals.”

♻️ Proposed rename
-using obj_accel_create_fn_t =
+using objAccelCreateFn =
     std::function<std::unique_ptr<nixlObjEngineImpl>(const nixlBackendInitParams *)>;
-using obj_accel_create_with_clients_fn_t =
+using objAccelCreateWithClientsFn =
     std::function<std::unique_ptr<nixlObjEngineImpl>(const nixlBackendInitParams *,
                                                      std::shared_ptr<iS3Client>,
                                                      std::shared_ptr<iS3Client>)>;
 
 struct objAccelEngineEntry {
-    obj_accel_create_fn_t create;
-    obj_accel_create_with_clients_fn_t createWithClients;
+    objAccelCreateFn create;
+    objAccelCreateWithClientsFn createWithClients;
 };
@@
     objAccelEngineRegistrar(const std::string &type,
-                            obj_accel_create_fn_t create,
-                            obj_accel_create_with_clients_fn_t create_with_clients) {
+                            objAccelCreateFn create,
+                            objAccelCreateWithClientsFn create_with_clients) {

Also applies to: 58-63

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/plugins/obj/obj_engine_registry.h` around lines 19 - 28, The type alias
names obj_accel_create_fn_t and obj_accel_create_with_clients_fn_t violate the
repo's lowerCamelCase type/function naming rule; rename them to objAccelCreateFn
and objAccelCreateWithClientsFn and update all usages (notably in the struct
objAccelEngineEntry and the registrar objAccelEngineRegistrar) to use the new
identifiers, ensuring function signatures remain unchanged (std::function
returning std::unique_ptr<nixlObjEngineImpl> with the same parameters).
test/gtest/unit/obj/mock_dell_s3_client.cpp (1)

6-8: ⚠️ Potential issue | 🟡 Minor

Run clang-format on this file before merging.

The Clang Format Check pipeline still reports mock_dell_s3_client.cpp differs from clang-format-19 output. Reformat the file rather than hand-adjusting specific lines. Based on learnings: “When reviewing CI clang-format failures, verify the exact file and line numbers from the CI logs before commenting.”

Also applies to: 58-58

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/gtest/unit/obj/mock_dell_s3_client.cpp` around lines 6 - 8, Run the
repository's clang-format (the same version used by CI, e.g., clang-format-19)
on test/gtest/unit/obj/mock_dell_s3_client.cpp and commit the reformatted file
rather than hand-editing lines; ensure the includes shown ("mock_s3_client.h",
"mock_client_registry.h", "s3_accel/dell/rdma_interface.h") are formatted
according to the project style so the clang-format check in CI passes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/plugins/obj/obj_engine_registry.h`:
- Around line 19-28: The type alias names obj_accel_create_fn_t and
obj_accel_create_with_clients_fn_t violate the repo's lowerCamelCase
type/function naming rule; rename them to objAccelCreateFn and
objAccelCreateWithClientsFn and update all usages (notably in the struct
objAccelEngineEntry and the registrar objAccelEngineRegistrar) to use the new
identifiers, ensuring function signatures remain unchanged (std::function
returning std::unique_ptr<nixlObjEngineImpl> with the same parameters).

In `@test/gtest/unit/obj/mock_dell_s3_client.cpp`:
- Around line 6-8: Run the repository's clang-format (the same version used by
CI, e.g., clang-format-19) on test/gtest/unit/obj/mock_dell_s3_client.cpp and
commit the reformatted file rather than hand-editing lines; ensure the includes
shown ("mock_s3_client.h", "mock_client_registry.h",
"s3_accel/dell/rdma_interface.h") are formatted according to the project style
so the clang-format check in CI passes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 26cc2364-ea27-45fb-a456-49b508cd4fd9

📥 Commits

Reviewing files that changed from the base of the PR and between e76d5d2 and 2eff9b8.

📒 Files selected for processing (13)
  • src/plugins/obj/README.md
  • src/plugins/obj/meson.build
  • src/plugins/obj/obj_backend.cpp
  • src/plugins/obj/obj_engine_registry.cpp
  • src/plugins/obj/obj_engine_registry.h
  • src/plugins/obj/s3_accel/dell/engine_impl.cpp
  • src/plugins/obj/s3_accel/engine_impl.cpp
  • src/utils/object/engine_utils.h
  • test/gtest/unit/obj/meson.build
  • test/gtest/unit/obj/mock_client_registry.h
  • test/gtest/unit/obj/mock_dell_s3_client.cpp
  • test/gtest/unit/obj/mock_s3_client.h
  • test/gtest/unit/obj/obj.cpp
💤 Files with no reviewable changes (1)
  • src/utils/object/engine_utils.h

Replace the #ifdef ladder in obj_backend.cpp with a self-registration
pattern.  Each accelerated engine (S3Accel, Dell) registers itself via
a static objAccelEngineRegistrar, and obj_backend.cpp dispatches
through the registry.  This makes it trivial to add new engines
without modifying the factory function.

Extract mock S3 client classes into separate headers for reuse, and
introduce a mock client registry mirroring the production engine
registry pattern.

Signed-off-by: Olivier Garaud <olivier.garaud@scality.com>
ofer
ofer previously approved these changes Apr 28, 2026
Add braces around single-line if bodies to comply with the project's
clang-format configuration.

Signed-off-by: Olivier Garaud <olivier.garaud@scality.com>
@ofer

ofer commented May 28, 2026

Copy link
Copy Markdown
Contributor

/ok to test ea867bb

@aranadive

Copy link
Copy Markdown
Contributor

@oliviergaraud can you rebase to pick up some CI fixes?

@oliviergaraud

Copy link
Copy Markdown
Contributor Author

@oliviergaraud can you rebase to pick up some CI fixes?

done

@aranadive

Copy link
Copy Markdown
Contributor

/ok to test dcd9ea4

@aranadive

Copy link
Copy Markdown
Contributor

/build

@ofer

ofer commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

/build

2 similar comments
@ofer

ofer commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

/build

@ofer

ofer commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

/build

@aranadive

Copy link
Copy Markdown
Contributor

@oliviergaraud can you rebase your PRs to latest main?

@ofer

ofer commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

/build

@oliviergaraud

Copy link
Copy Markdown
Contributor Author

@oliviergaraud can you rebase your PRs to latest main?

done

@aranadive

Copy link
Copy Markdown
Contributor

/ok to test 72343a0

@aranadive

Copy link
Copy Markdown
Contributor

/build

@ovidiusm
ovidiusm merged commit 46752b4 into ai-dynamo:main Jun 5, 2026
16 checks passed

This branch was previously deployed

1 inactive deployment
SWX_AWS — 72343a0f Deployed Jun 5, 2026 by copy-pr-bot[bot] via Run AWS Tests #7607
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants