Skip to content

Split gateway sources into a middleware-neutral core layer for independent testing and structural enforcement #391

@bburda

Description

@bburda

Summary

Today the gateway package compiles all of its source files into a single gateway_lib static library that links rclcpp, rcl_interfaces, action messages, ros2_medkit_msgs, and ros2_medkit_serialization. Most of that source — HTTP routing, request handlers, JWT authentication, fault model (debounce, SQLite storage, correlation), peer aggregation (mDNS discovery, entity merger, SSE proxy), the manifest parser, the entity cache, the lock/bulk-data/subscription/script/update managers, the OpenAPI builder, and the provider interface contracts — has no inherent dependency on ROS. Mixing the two in one library produces several friction points:

  • Testing requires a full ROS environment. Every gateway unit test brings in ament_target_dependencies and pulls rclcpp onto the link line, even when the code under test (e.g. auth_manager, fault_storage, entity_merger, peer_client) doesn't touch ROS APIs.
  • Slower iteration on business logic. The precompiled-header set bundles rclcpp/rclcpp.hpp, so any change in a neutral header invalidates a PCH that includes ROS headers and triggers larger rebuilds than necessary.
  • No structural enforcement that new neutral code stays neutral — there is no CI guard preventing somebody from quietly adding #include <rclcpp/rclcpp.hpp> inside the JWT manager or the SQLite trigger store.
  • Provider abstractions are blurred. The DataProvider / OperationProvider / FaultProvider / LogProvider / IntrospectionProvider interfaces are pure C++17, but they sit alongside their ROS-specific default implementations (e.g. Ros2TopicDataProvider) under the same include root, making the interface/implementation boundary harder to reason about.

Proposed solution (optional)

Split the package's sources into two named layers, both inside the existing ros2_medkit_gateway package, without splitting into a separate colcon package yet:

  • core/ — middleware-neutral business logic. Compiles into a new gateway_core static library that links only header-only and C-level externals (cpp-httplib, nlohmann/json, yaml-cpp, tl::expected, jwt-cpp, OpenSSL, SQLite, dl). No rclcpp, no rcl_interfaces, no message-package transitive includes. Enforced by:
    • a grep-based linter (scripts/check_core_purity.sh wired as gateway_core_purity CTest);
    • a link-time smoke test (test_gateway_core_smoke) that compiles a translation unit including a sampling of core/ headers and links exclusively against gateway_core + GTest, with no ament_target_dependencies. A regression in either guard fails the build.
  • The remainder of the source tree — gateway_node, the ROS-coupled managers, runtime_discovery, ros2_topic_data_provider, the trigger subscribers, etc. — stays at its current path and forms a gateway_ros2 static library that publicly links gateway_core.

The gateway_node executable and existing tests link gateway_ros2 so they transitively get both layers; nothing changes for downstream consumers of the gateway. Headers that move acquire a one-line forwarding shim at their old paths so out-of-tree plugins continue to compile without modification.

This issue tracks only the structural relocation. Subsequent issues will cover the per-manager refactors (data access, operation, configuration, fault facade, log, trigger) that introduce provider injection so the managers themselves move into core/.


Additional context (optional)

Outcome metrics expected after the relocation:

  • 35 source files compile via gateway_core without any ROS link dependency.
  • Two structural CI guards: gateway_core_purity (grep) and gateway_core_smoke (link-time).
  • PCH split: gateway_core PCH contains std + json + httplib + tl::expected; gateway_ros2 PCH adds rclcpp/rclcpp.hpp on top.
  • Backwards-compat shim headers at every legacy path so out-of-tree consumers (graph_provider, opcua, sovd_service_interface, linux_introspection, param_beacon, topic_beacon) compile unchanged.
  • Existing test suite (~2500 unit, ~3200 integration, ~2600 clang-tidy targets) stays green.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions