Skip to content

Performance/networking optimizations#45

Open
MarioIvancik wants to merge 9 commits intomasterfrom
BAF-1122/optimizations
Open

Performance/networking optimizations#45
MarioIvancik wants to merge 9 commits intomasterfrom
BAF-1122/optimizations

Conversation

@MarioIvancik
Copy link
Member

@MarioIvancik MarioIvancik commented Jul 18, 2025

https://youtrack.bringauto.com/issue/BAF-1122/Module-Gateway-performance

Summary by CodeRabbit

  • New Features

    • Added support for a new DUMMY protocol and a dummy communication channel.
    • Build-time configurable minimum logger verbosity to filter logs and improve performance.
  • Improvements

    • Widespread const-correctness and API immutability enhancements.
    • Replaced several ordered maps with unordered maps for faster lookups.
    • Exposed remote endpoint address retrieval and centralized its use in logs.
    • Logger initialization and compile-time filtering optimized; stdio sync disabled for perf.
  • Bug Fixes

    • Typos and documentation/parameter-name corrections.
  • Documentation

    • README updated with new CMake argument for logger verbosity.
  • Tests

    • Unit tests extended for DUMMY protocol and logger verbosity changes.

@MarioIvancik MarioIvancik self-assigned this Jul 18, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jul 18, 2025

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

Adds a compile-time logger verbosity option and LoggerWrapper; introduces a DUMMY protocol and DummyCommunication channel; converts many APIs to const-correct signatures; switches several ordered maps to unordered_map; updates enum/constant utilities and adjusts related tests and CMake/README documentation.

Changes

Cohort / File(s) Summary
Build & docs
CMakeLists.txt, README.md
Bump module version; add MODULE_GATEWAY_MINIMUM_LOGGER_VERBOSITY CMake option and document allowed values.
Logger core & validation
include/bringauto/settings/LoggerWrapper.hpp, include/bringauto/settings/LoggerId.hpp, source/bringauto/settings/LoggerId.cpp, include/bringauto/settings/LoggerId.cpp
Add LoggerWrapper template, compile-time verbosity validation, and adapt logger aliasing to use macro-derived verbosity.
Logger usage & init
main.cpp, test/include/*Tests.hpp (InternalServer, ErrorAggregator, ExternalConnection, StatusAggregator)
Logger init now uses toLoggerVerbosity(MODULE_GATEWAY_MINIMUM_LOGGER_VERBOSITY); main disables iostream sync for performance; tests updated to use macro-derived verbosity.
Enum/constants
include/bringauto/common_utils/EnumUtils.hpp, source/bringauto/common_utils/EnumUtils.cpp, include/bringauto/settings/Constants.hpp, test/source/EnumUtilsTests.cpp
Add DUMMY protocol constant; convert some enum-to-string functions to constexpr/std::string_view; add DUMMY handling and update tests.
New dummy protocol channel
include/bringauto/external_client/connection/communication/DummyCommunication.hpp, source/bringauto/external_client/connection/communication/DummyCommunication.cpp
Add DummyCommunication implementing ICommunicationChannel for DUMMY protocol (initialize, send, receive, close).
External client & connections
include/bringauto/external_client/ExternalClient.hpp, source/bringauto/external_client/ExternalClient.cpp, include/bringauto/external_client/connection/ExternalConnection.hpp, source/bringauto/external_client/connection/ExternalConnection.cpp
Add DUMMY support, change constructor params to const refs, switch maps to unordered_map, replace repeated lookups with iterator-based accesses, and mark several methods const.
ICommunication interface
include/bringauto/external_client/connection/communication/ICommunicationChannel.hpp, include/bringauto/external_client/connection/communication/MqttCommunication.hpp, source/bringauto/external_client/connection/communication/MqttCommunication.cpp
ICommunicationChannel now takes settings by value and moves; removed unused includes; changed connection reinitialize logic in MqttCommunication.
Protobuf & buffer handling
include/bringauto/common_utils/ProtobufUtils.hpp, source/bringauto/common_utils/ProtobufUtils.cpp, include/bringauto/modules/Buffer.hpp
Make copyStatus/copyCommand take const modules::Buffer&, add local size variables, use memcpy safely, and remove unused includes.
Const-correctness & API tweaks
multiple headers/sources: include/bringauto/modules/ModuleHandler.hpp, source/bringauto/modules/ModuleHandler.cpp, include/bringauto/modules/ModuleManagerLibraryHandler.hpp, source/bringauto/modules/ModuleManagerLibraryHandler.cpp, include/bringauto/modules/StatusAggregator.hpp, source/bringauto/modules/StatusAggregator.cpp, include/bringauto/internal_server/InternalServer.hpp, source/bringauto/internal_server/InternalServer.cpp, include/bringauto/external_client/ErrorAggregator.hpp, source/bringauto/external_client/ErrorAggregator.cpp, include/bringauto/external_client/connection/messages/*, include/bringauto/settings/SettingsParser.hpp, source/bringauto/settings/SettingsParser.cpp, include/bringauto/structures/*, source/bringauto/*
Widespread const-qualifications on methods and parameters, parameter renames, removal of unused includes, tighter local const usage, and small API additions (e.g., Connection::remoteEndpointAddress()).
Container type changes
include/bringauto/settings/Settings.hpp, include/bringauto/structures/ExternalConnectionSettings.hpp, include/bringauto/structures/ModuleLibrary.hpp, source/bringauto/structures/ModuleLibrary.cpp, test/include/testing_utils/ConfigMock.hpp
Replace several std::map usages with std::unordered_map for module paths, protocol settings, and related structures; update function signatures accordingly.
Tests & test utils
test/source/*, test/include/*, test/include/testing_utils/ConfigMock.hpp
Update tests to account for new enum/protocol, change logger init to macro-derived verbosity, adapt mocks to unordered_map, and tweak some test expectations/comments.
Docker
Dockerfile
Bump MISSION_MODULE_VERSION arg from v1.2.12 → v1.2.13.

Sequence Diagram(s)

sequenceDiagram
    participant Config as CMake/Config
    participant Main as main.cpp
    participant Logger as LoggerWrapper
    participant Tests as Test Binaries

    Developer->>Config: Set MODULE_GATEWAY_MINIMUM_LOGGER_VERBOSITY
    Config->>Main: Compile with macro
    Main->>Logger: Logger::init(toLoggerVerbosity(MODULE_GATEWAY_MINIMUM_LOGGER_VERBOSITY))
    Logger->>Logger: compile-time filter (template param)
    Tests->>Logger: init in test setup
    Logger-->>Main: Filtered log output
Loading
sequenceDiagram
    participant Settings as SettingsParser
    participant External as ExternalClient
    participant Comm as DummyCommunication

    Settings->>External: parse connection with ProtocolType::DUMMY
    External->>Comm: construct DummyCommunication(settings)
    Comm->>External: initializeConnection()
    External->>Comm: sendMessage(...)
    Comm-->>External: true / nullptr (receive)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • koudis
🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Performance/networking optimizations' is vague and generic, using broad terms without describing specific changes made in the changeset. Use a more specific title that highlights the main changes, such as 'Add logger verbosity configuration and refactor for const-correctness' or 'Implement compile-time logger filtering and performance improvements'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch BAF-1122/optimizations

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.

Copy link

@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

🧹 Nitpick comments (3)
include/bringauto/structures/AtomicQueue.hpp (1)

33-36: Clarify return-value semantics in the fresh comment while you’re here

Nice typo fix. Since you’re touching the docblock anyway, consider spelling out that the function returns true only when the timeout expired and the queue is still empty:

- * @return true if the queue is empty
+ * @return true if the queue is still empty after the timeout has elapsed,
+ *         false if a value became available before the timeout.
README.md (1)

80-88: LGTM! Clear documentation of new logger verbosity option.

The documentation clearly explains the new MINIMUM_LOGGER_VERBOSITY CMake option and its performance benefits through compile-time log filtering. This aligns well with the PR's performance optimization objectives.

Consider fixing the minor formatting inconsistency flagged by markdownlint - the list uses asterisks while other lists in the file use dashes.

-* MINIMUM_LOGGER_VERBOSITY=0/1/2/3/4
+- MINIMUM_LOGGER_VERBOSITY=0/1/2/3/4
source/bringauto/common_utils/EnumUtils.cpp (1)

13-15: DUMMY protocol support added correctly.

The logic for handling the DUMMY protocol type is consistent with the existing MQTT protocol handling. However, there's an indentation inconsistency - the new code uses spaces while the existing code appears to use tabs.

Consider fixing the indentation to match the existing style:

-	} else if(toEnum == settings::Constants::DUMMY) {
-        return structures::ProtocolType::DUMMY;
-    }
+	} else if(toEnum == settings::Constants::DUMMY) {
+		return structures::ProtocolType::DUMMY;
+	}

Copy link

@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)
README.md (2)

80-82: Markdown-lint MD004 violation – switch to dash bullets for consistency

markdownlint flags the new bullet because the project’s doc style-guide prefers - over *.
Since the surrounding list items (61-78) already use *, you can either:

  1. Adopt dashes here and everywhere else (preferred ‑ silences the linter globally), or
  2. Add an explicit rule override to keep asterisks.

Example fix for the new item:

-* MODULE_GATEWAY_MINIMUM_LOGGER_VERBOSITY=0/1/2/3/4
+- MODULE_GATEWAY_MINIMUM_LOGGER_VERBOSITY=0/1/2/3/4

83-88: Spell out the enum names to avoid “magic numbers”

Readers unfamiliar with ba-logger may not know which numeric level maps to which macro/enum.
Consider appending the symbolic names once to improve clarity:

-  - 0: DEBUG
-  - 1: INFO
-  - 2: WARNING
-  - 3: ERROR
-  - 4: CRITICAL
+  - 0 (`BA_LOGGER_VERBOSITY_DEBUG`): DEBUG  
+  - 1 (`BA_LOGGER_VERBOSITY_INFO`): INFO  
+  - 2 (`BA_LOGGER_VERBOSITY_WARNING`): WARNING  
+  - 3 (`BA_LOGGER_VERBOSITY_ERROR`): ERROR  
+  - 4 (`BA_LOGGER_VERBOSITY_CRITICAL`): CRITICAL

This keeps the README self-contained and reduces the mental jump to the codebase/macros.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0cf2f5e and b4bd01a.

📒 Files selected for processing (9)
  • CMakeLists.txt (1 hunks)
  • Dockerfile (1 hunks)
  • README.md (1 hunks)
  • include/bringauto/settings/LoggerId.hpp (1 hunks)
  • include/bringauto/settings/LoggerWrapper.hpp (1 hunks)
  • include/bringauto/structures/Connection.hpp (1 hunks)
  • main.cpp (3 hunks)
  • source/bringauto/common_utils/ProtobufUtils.cpp (5 hunks)
  • source/bringauto/internal_server/InternalServer.cpp (18 hunks)
🧠 Learnings (1)
README.md (6)

Learnt from: koudis
PR: #43
File: CMakeLists.txt:11-14
Timestamp: 2025-06-29T18:12:34.666Z
Learning: In the ModuleGateway project's CMakeLists.txt, compile definitions for version strings are intentionally set with escaped quotes using CMDEF_COMPILE_DEFINITIONS to produce compiler flags like -DMODULE_GATEWAY_VERSION="1.3.3", ensuring the macro expands to a proper string literal in C++ code.

Learnt from: MarioIvancik
PR: #38
File: include/bringauto/structures/LoggingSettings.hpp:10-15
Timestamp: 2024-10-31T10:45:48.494Z
Learning: In the ModuleGateway project, values in the structures defined in include/bringauto/structures/LoggingSettings.hpp are validated in SettingsParser.cpp, so additional validation within the structures is unnecessary.

Learnt from: Mayt34
PR: bringauto/transparent-module#1
File: CMakeLists.txt:15-20
Timestamp: 2024-10-03T17:41:56.410Z
Learning: In the transparent_module project, all modules should be built by default; FLEET_PROTOCOL_BUILD_MODULE_GATEWAY and FLEET_PROTOCOL_BUILD_EXTERNAL_SERVER should be set to ON by default.

Learnt from: Mayt34
PR: bringauto/transparent-module#1
File: CMakeLists.txt:15-20
Timestamp: 2024-10-09T05:03:50.249Z
Learning: In the transparent_module project, all modules should be built by default; FLEET_PROTOCOL_BUILD_MODULE_GATEWAY and FLEET_PROTOCOL_BUILD_EXTERNAL_SERVER should be set to ON by default.

Learnt from: mikusaq
PR: bacpack-system/packager#24
File: modules/bringauto_log/Handler.go:40-54
Timestamp: 2024-10-09T05:03:50.249Z
Learning: The bringauto_log module does not currently use the debug log level.

Learnt from: mikusaq
PR: bacpack-system/packager#24
File: modules/bringauto_log/Handler.go:40-54
Timestamp: 2024-09-30T11:00:40.818Z
Learning: The bringauto_log module does not currently use the debug log level.

🪛 markdownlint-cli2 (0.17.2)
README.md

80-80: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)

✅ Files skipped from review due to trivial changes (1)
  • Dockerfile
🚧 Files skipped from review as they are similar to previous changes (7)
  • include/bringauto/structures/Connection.hpp
  • main.cpp
  • source/bringauto/common_utils/ProtobufUtils.cpp
  • CMakeLists.txt
  • include/bringauto/settings/LoggerWrapper.hpp
  • include/bringauto/settings/LoggerId.hpp
  • source/bringauto/internal_server/InternalServer.cpp
🧰 Additional context used
🧠 Learnings (1)
README.md (6)

Learnt from: koudis
PR: #43
File: CMakeLists.txt:11-14
Timestamp: 2025-06-29T18:12:34.666Z
Learning: In the ModuleGateway project's CMakeLists.txt, compile definitions for version strings are intentionally set with escaped quotes using CMDEF_COMPILE_DEFINITIONS to produce compiler flags like -DMODULE_GATEWAY_VERSION="1.3.3", ensuring the macro expands to a proper string literal in C++ code.

Learnt from: MarioIvancik
PR: #38
File: include/bringauto/structures/LoggingSettings.hpp:10-15
Timestamp: 2024-10-31T10:45:48.494Z
Learning: In the ModuleGateway project, values in the structures defined in include/bringauto/structures/LoggingSettings.hpp are validated in SettingsParser.cpp, so additional validation within the structures is unnecessary.

Learnt from: Mayt34
PR: bringauto/transparent-module#1
File: CMakeLists.txt:15-20
Timestamp: 2024-10-03T17:41:56.410Z
Learning: In the transparent_module project, all modules should be built by default; FLEET_PROTOCOL_BUILD_MODULE_GATEWAY and FLEET_PROTOCOL_BUILD_EXTERNAL_SERVER should be set to ON by default.

Learnt from: Mayt34
PR: bringauto/transparent-module#1
File: CMakeLists.txt:15-20
Timestamp: 2024-10-09T05:03:50.249Z
Learning: In the transparent_module project, all modules should be built by default; FLEET_PROTOCOL_BUILD_MODULE_GATEWAY and FLEET_PROTOCOL_BUILD_EXTERNAL_SERVER should be set to ON by default.

Learnt from: mikusaq
PR: bacpack-system/packager#24
File: modules/bringauto_log/Handler.go:40-54
Timestamp: 2024-10-09T05:03:50.249Z
Learning: The bringauto_log module does not currently use the debug log level.

Learnt from: mikusaq
PR: bacpack-system/packager#24
File: modules/bringauto_log/Handler.go:40-54
Timestamp: 2024-09-30T11:00:40.818Z
Learning: The bringauto_log module does not currently use the debug log level.

🪛 markdownlint-cli2 (0.17.2)
README.md

80-80: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)

Copy link

@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)
include/bringauto/settings/LoggerId.hpp (1)

34-45: Consider making the DEBUG case explicit.

The function correctly converts string verbosity levels to enum values. However, the "DEBUG" case is handled implicitly by the default return. Consider making it explicit for clarity:

 constexpr logging::LoggerVerbosity toLoggerVerbosity(std::string_view verbosityString) {
-	if (verbosityString == "INFO") {
+	if (verbosityString == "DEBUG") {
+		return logging::LoggerVerbosity::Debug;
+	} else if (verbosityString == "INFO") {
 		return logging::LoggerVerbosity::Info;
 	} else if (verbosityString == "WARNING") {
 		return logging::LoggerVerbosity::Warning;
 	} else if (verbosityString == "ERROR") {
 		return logging::LoggerVerbosity::Error;
 	} else if (verbosityString == "CRITICAL") {
 		return logging::LoggerVerbosity::Critical;
 	}
-	return logging::LoggerVerbosity::Debug;
+	// This should never be reached due to static_assert validation
+	return logging::LoggerVerbosity::Debug;
 }
README.md (1)

80-83: Good documentation of the new compile-time logging feature.

The documentation accurately describes the new MODULE_GATEWAY_MINIMUM_LOGGER_VERBOSITY CMake argument and its performance benefits. The listed verbosity levels match the implementation.

Fix the list style for consistency with the rest of the document:

-* MODULE_GATEWAY_MINIMUM_LOGGER_VERBOSITY=DEBUG/INFO/WARNING/ERROR/CRITICAL
+- MODULE_GATEWAY_MINIMUM_LOGGER_VERBOSITY=DEBUG/INFO/WARNING/ERROR/CRITICAL
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b4bd01a and 4a84ce1.

📒 Files selected for processing (4)
  • CMakeLists.txt (1 hunks)
  • README.md (1 hunks)
  • include/bringauto/external_client/connection/communication/DummyCommunication.hpp (1 hunks)
  • include/bringauto/settings/LoggerId.hpp (1 hunks)
🧠 Learnings (2)
include/bringauto/settings/LoggerId.hpp (5)

Learnt from: MarioIvancik
PR: #38
File: include/bringauto/structures/LoggingSettings.hpp:10-15
Timestamp: 2024-10-31T10:45:48.494Z
Learning: In the ModuleGateway project, values in the structures defined in include/bringauto/structures/LoggingSettings.hpp are validated in SettingsParser.cpp, so additional validation within the structures is unnecessary.

Learnt from: MarioIvancik
PR: #38
File: include/bringauto/structures/LoggingSettings.hpp:26-31
Timestamp: 2024-10-31T10:44:39.657Z
Learning: In the ModuleGateway project, logging settings are validated in SettingsParser, so additional validation in the LoggingSettings structure is not necessary.

Learnt from: koudis
PR: #43
File: CMakeLists.txt:11-14
Timestamp: 2025-06-29T18:12:34.666Z
Learning: In the ModuleGateway project's CMakeLists.txt, compile definitions for version strings are intentionally set with escaped quotes using CMDEF_COMPILE_DEFINITIONS to produce compiler flags like -DMODULE_GATEWAY_VERSION="1.3.3", ensuring the macro expands to a proper string literal in C++ code.

Learnt from: Melky-Phoe
PR: bringauto/fleet-management-http-api#17
File: fleet_management_api/main.py:42-42
Timestamp: 2024-09-18T06:54:20.565Z
Learning: The team prefers using constants for configuration values like the logging configuration file path instead of making them configurable via command-line arguments or configuration parameters unless necessary.

Learnt from: Melky-Phoe
PR: bringauto/fleet-management-http-api#17
File: fleet_management_api/main.py:42-42
Timestamp: 2024-10-09T05:03:50.249Z
Learning: The team prefers using constants for configuration values like the logging configuration file path instead of making them configurable via command-line arguments or configuration parameters unless necessary.

README.md (6)

Learnt from: koudis
PR: #43
File: CMakeLists.txt:11-14
Timestamp: 2025-06-29T18:12:34.666Z
Learning: In the ModuleGateway project's CMakeLists.txt, compile definitions for version strings are intentionally set with escaped quotes using CMDEF_COMPILE_DEFINITIONS to produce compiler flags like -DMODULE_GATEWAY_VERSION="1.3.3", ensuring the macro expands to a proper string literal in C++ code.

Learnt from: MarioIvancik
PR: #38
File: include/bringauto/structures/LoggingSettings.hpp:10-15
Timestamp: 2024-10-31T10:45:48.494Z
Learning: In the ModuleGateway project, values in the structures defined in include/bringauto/structures/LoggingSettings.hpp are validated in SettingsParser.cpp, so additional validation within the structures is unnecessary.

Learnt from: mikusaq
PR: bacpack-system/packager#24
File: modules/bringauto_log/Handler.go:40-54
Timestamp: 2024-10-09T05:03:50.249Z
Learning: The bringauto_log module does not currently use the debug log level.

Learnt from: mikusaq
PR: bacpack-system/packager#24
File: modules/bringauto_log/Handler.go:40-54
Timestamp: 2024-09-30T11:00:40.818Z
Learning: The bringauto_log module does not currently use the debug log level.

Learnt from: Mayt34
PR: bringauto/transparent-module#1
File: CMakeLists.txt:15-20
Timestamp: 2024-10-03T17:41:56.410Z
Learning: In the transparent_module project, all modules should be built by default; FLEET_PROTOCOL_BUILD_MODULE_GATEWAY and FLEET_PROTOCOL_BUILD_EXTERNAL_SERVER should be set to ON by default.

Learnt from: Mayt34
PR: bringauto/transparent-module#1
File: CMakeLists.txt:15-20
Timestamp: 2024-10-09T05:03:50.249Z
Learning: In the transparent_module project, all modules should be built by default; FLEET_PROTOCOL_BUILD_MODULE_GATEWAY and FLEET_PROTOCOL_BUILD_EXTERNAL_SERVER should be set to ON by default.

🪛 markdownlint-cli2 (0.17.2)
README.md

80-80: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)

🚧 Files skipped from review as they are similar to previous changes (2)
  • CMakeLists.txt
  • include/bringauto/external_client/connection/communication/DummyCommunication.hpp
🧰 Additional context used
🧠 Learnings (2)
include/bringauto/settings/LoggerId.hpp (5)

Learnt from: MarioIvancik
PR: #38
File: include/bringauto/structures/LoggingSettings.hpp:10-15
Timestamp: 2024-10-31T10:45:48.494Z
Learning: In the ModuleGateway project, values in the structures defined in include/bringauto/structures/LoggingSettings.hpp are validated in SettingsParser.cpp, so additional validation within the structures is unnecessary.

Learnt from: MarioIvancik
PR: #38
File: include/bringauto/structures/LoggingSettings.hpp:26-31
Timestamp: 2024-10-31T10:44:39.657Z
Learning: In the ModuleGateway project, logging settings are validated in SettingsParser, so additional validation in the LoggingSettings structure is not necessary.

Learnt from: koudis
PR: #43
File: CMakeLists.txt:11-14
Timestamp: 2025-06-29T18:12:34.666Z
Learning: In the ModuleGateway project's CMakeLists.txt, compile definitions for version strings are intentionally set with escaped quotes using CMDEF_COMPILE_DEFINITIONS to produce compiler flags like -DMODULE_GATEWAY_VERSION="1.3.3", ensuring the macro expands to a proper string literal in C++ code.

Learnt from: Melky-Phoe
PR: bringauto/fleet-management-http-api#17
File: fleet_management_api/main.py:42-42
Timestamp: 2024-09-18T06:54:20.565Z
Learning: The team prefers using constants for configuration values like the logging configuration file path instead of making them configurable via command-line arguments or configuration parameters unless necessary.

Learnt from: Melky-Phoe
PR: bringauto/fleet-management-http-api#17
File: fleet_management_api/main.py:42-42
Timestamp: 2024-10-09T05:03:50.249Z
Learning: The team prefers using constants for configuration values like the logging configuration file path instead of making them configurable via command-line arguments or configuration parameters unless necessary.

README.md (6)

Learnt from: koudis
PR: #43
File: CMakeLists.txt:11-14
Timestamp: 2025-06-29T18:12:34.666Z
Learning: In the ModuleGateway project's CMakeLists.txt, compile definitions for version strings are intentionally set with escaped quotes using CMDEF_COMPILE_DEFINITIONS to produce compiler flags like -DMODULE_GATEWAY_VERSION="1.3.3", ensuring the macro expands to a proper string literal in C++ code.

Learnt from: MarioIvancik
PR: #38
File: include/bringauto/structures/LoggingSettings.hpp:10-15
Timestamp: 2024-10-31T10:45:48.494Z
Learning: In the ModuleGateway project, values in the structures defined in include/bringauto/structures/LoggingSettings.hpp are validated in SettingsParser.cpp, so additional validation within the structures is unnecessary.

Learnt from: mikusaq
PR: bacpack-system/packager#24
File: modules/bringauto_log/Handler.go:40-54
Timestamp: 2024-10-09T05:03:50.249Z
Learning: The bringauto_log module does not currently use the debug log level.

Learnt from: mikusaq
PR: bacpack-system/packager#24
File: modules/bringauto_log/Handler.go:40-54
Timestamp: 2024-09-30T11:00:40.818Z
Learning: The bringauto_log module does not currently use the debug log level.

Learnt from: Mayt34
PR: bringauto/transparent-module#1
File: CMakeLists.txt:15-20
Timestamp: 2024-10-03T17:41:56.410Z
Learning: In the transparent_module project, all modules should be built by default; FLEET_PROTOCOL_BUILD_MODULE_GATEWAY and FLEET_PROTOCOL_BUILD_EXTERNAL_SERVER should be set to ON by default.

Learnt from: Mayt34
PR: bringauto/transparent-module#1
File: CMakeLists.txt:15-20
Timestamp: 2024-10-09T05:03:50.249Z
Learning: In the transparent_module project, all modules should be built by default; FLEET_PROTOCOL_BUILD_MODULE_GATEWAY and FLEET_PROTOCOL_BUILD_EXTERNAL_SERVER should be set to ON by default.

🪛 markdownlint-cli2 (0.17.2)
README.md

80-80: Unordered list style
Expected: dash; Actual: asterisk

(MD004, ul-style)

🔇 Additional comments (4)
include/bringauto/settings/LoggerId.hpp (4)

3-7: LGTM: Clean macro definition with proper default.

The include and macro definition are well-structured. The conditional definition allows CMake to override the default while providing a sensible fallback.


19-21: Well-implemented constexpr string comparison.

The use of std::string_view for compile-time string comparison is efficient and appropriate. This enables the static_assert validation at compile time.


23-28: Excellent compile-time validation.

The static_assert provides robust validation of the verbosity level macro at compile time, preventing invalid configurations from compiling. This addresses potential runtime errors early in the build process.


47-50: Excellent design for compile-time logging optimization.

The type aliases create a clean abstraction that enables compile-time log filtering. The Logger alias uses LoggerWrapper with compile-time verbosity evaluation, which should provide the performance benefits mentioned in the PR objectives.

@sonarqubecloud
Copy link

if (!socket.is_open()) {
return "(N/A, socket is not open)";
}
return socket.remote_endpoint().address().to_string();
Copy link
Member

Choose a reason for hiding this comment

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

Are we sure this will always work and does not omit exceptions?

INVALID = -1,
MQTT
MQTT,
DUMMY
Copy link
Member

Choose a reason for hiding this comment

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

Documentation for each Enum element?

connectMessage->set_company(company);
connectMessage->set_vehiclename(vehicleName);

connectMessage->mutable_devices()->Reserve(devices.size());
Copy link
Member

Choose a reason for hiding this comment

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

Why reverse?

return;
}
else if (client_ != nullptr) {
if (client_ != nullptr) {
Copy link
Member

Choose a reason for hiding this comment

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

Why was the "else" deleted? Oo, I see if it is connected I want to close the connection in this case.

return connection->deviceId->isSame(toCompare->deviceId);
});
const auto it = std::find_if(connectedDevices_.begin(), connectedDevices_.end(),
[&connection](const std::shared_ptr<structures::Connection> &toCompare) {
Copy link
Member

Choose a reason for hiding this comment

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

Indent?

@jiriskuta jiriskuta force-pushed the BAF-1122/optimizations branch from bb7ca23 to 115f620 Compare February 18, 2026 19:36
@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
4 New Major Issues (required ≤ 0)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

Copy link

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

Caution

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

⚠️ Outside diff range comments (2)
source/bringauto/modules/StatusAggregator.cpp (1)

30-35: ⚠️ Potential issue | 🟠 Major

aggregateStatus returns an empty Buffer {} on failure, contradicting the log message and likely corrupting device state.

Line 33 warns "returning current status buffer" but the function unconditionally returns aggregatedStatusBuff, which remains default-initialized to Buffer {} when module_->aggregateStatus fails. Both callers propagate this empty buffer:

  • aggregateSetStatusdeviceState.setStatus({}) — overwrites the device's current status with an empty buffer.
  • aggregateSetSendStatusdeviceState.setStatusAndResetTimer({}) + pushes {} to the aggregated message queue.

Either currStatus should be returned on the error path to preserve existing state (matching the log intent), or the error path must be handled more deliberately.

🐛 Proposed fix
 Buffer
 StatusAggregator::aggregateStatus(const structures::StatusAggregatorDeviceState &deviceState, const Buffer &status,
 								  const unsigned int &device_type) const {
-	auto &currStatus = deviceState.getStatus();
+	const auto &currStatus = deviceState.getStatus();
 	Buffer aggregatedStatusBuff {};
 	if (module_->aggregateStatus(aggregatedStatusBuff, currStatus, status, device_type) != OK) {
 		log::logWarning("Error occurred while aggregating status, returning current status buffer");
+		return currStatus;
 	}
 	return aggregatedStatusBuff;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@source/bringauto/modules/StatusAggregator.cpp` around lines 30 - 35, The
current error path in StatusAggregator::aggregateStatus returns a
default-initialized aggregatedStatusBuff (Buffer {}) which contradicts the log
and overwrites device state; change the failure branch so that when
module_->aggregateStatus(aggregatedStatusBuff, currStatus, status, device_type)
!= OK you assign or return currStatus (the existing deviceState.getStatus())
instead of the empty aggregatedStatusBuff to preserve state — update the error
branch in aggregateStatus to set aggregatedStatusBuff = currStatus (or return
currStatus) so callers like aggregateSetStatus and aggregateSetSendStatus do not
receive and propagate an empty Buffer.
source/bringauto/modules/ModuleHandler.cpp (1)

15-21: ⚠️ Potential issue | 🟡 Minor

Unused variable deviceId in destroy() — dead code block.

The if(message.disconnected()) block creates deviceId but never uses it. The block is a no-op and will likely generate a compiler warning for the unused variable.

🧹 Proposed fix
 		auto &message = fromInternalQueue_->front();
-		if(message.disconnected()) {
-			auto deviceId = message.getDeviceId();
-		}
 		fromInternalQueue_->pop();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@source/bringauto/modules/ModuleHandler.cpp` around lines 15 - 21, In
destroy(), the if(message.disconnected()) block declares deviceId via
message.getDeviceId() but never uses it, causing dead code and compiler
warnings; remove the unused variable and the empty if block (or replace it with
the intended cleanup call if you meant to act on deviceId), i.e., in the loop
over fromInternalQueue_ eliminate the no-op if(message.disconnected()) { auto
deviceId = message.getDeviceId(); } so only fromInternalQueue_->pop() remains
(or add the actual disconnect handling using message.getDeviceId()).
🧹 Nitpick comments (13)
include/bringauto/external_client/connection/messages/SentMessagesHandler.hpp (1)

68-68: isDeviceConnected is missing const and [[nodiscard]] — inconsistent with sibling predicates.

isAnyDeviceConnected (line 75) is both const and [[nodiscard]]. If isDeviceConnected does not mutate state (which is implied by its query semantics), it should follow the same pattern.

♻️ Proposed fix
-	bool isDeviceConnected(const structures::DeviceIdentification &device);
+	[[nodiscard]] bool isDeviceConnected(const structures::DeviceIdentification &device) const;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@include/bringauto/external_client/connection/messages/SentMessagesHandler.hpp`
at line 68, The method declaration for isDeviceConnected should match the const
and [[nodiscard]] qualifiers used by its sibling predicate isAnyDeviceConnected:
update the declaration of isDeviceConnected(const
structures::DeviceIdentification &device) to [[nodiscard]] bool
isDeviceConnected(const structures::DeviceIdentification &device) const; so the
method is marked as a non-mutating, nodiscard query (and update any
corresponding definition/implementation of
SentMessagesHandler::isDeviceConnected to include the trailing const).
source/bringauto/external_client/connection/communication/MqttCommunication.cpp (1)

63-71: else ifif is a functional no-op; AI summary mischaracterises the change.

The early-return guard on lines 64–66 is still present in the new code:

if (client_ != nullptr && client_->is_connected()) {
    return;                    // ← still here, unchanged
}

Because the first branch always returns when true, execution only reaches line 67 when the first condition was false. In that case, both else if (client_ != nullptr) (old) and if (client_ != nullptr) (new) evaluate identically — all three cases produce the same outcome:

State Old New
client_ == nullptr connect() connect()
exists + connected return return
exists + disconnected closeConnection()connect() closeConnection()connect()

The AI summary's claim that "now it closes (if present) and then reconnects" (implying the early return was removed) is incorrect — no behavioral change has occurred.

The else if phrasing was marginally clearer since it made the mutual exclusion between the two branches explicit. Keeping else if (or adding a comment) would preserve that intent.

♻️ Optional: restore the more expressive `else if`
-	if (client_ != nullptr) {
+	else if (client_ != nullptr) {
 		closeConnection();
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@source/bringauto/external_client/connection/communication/MqttCommunication.cpp`
around lines 63 - 71, The change to MqttCommunication::initializeConnection
altered the branch from "else if (client_ != nullptr)" to a standalone "if
(client_ != nullptr)" which is functionally equivalent but less explicitly
signaling mutual exclusivity with the earlier early-return; restore the original
"else if (client_ != nullptr)" (or add a brief clarifying comment above the
early-return) so the intent that the connected case is mutually exclusive with
the disconnected-but-existing case is clear when reading the code; ensure
references to client_, client_->is_connected(), closeConnection(), and connect()
remain unchanged.
source/bringauto/modules/StatusAggregator.cpp (1)

16-18: Redundant devices.contains check is unreachable dead code.

is_device_valid (line 164) already verifies both is_device_type_supported and devices.contains(device). If it returns OK, the device is guaranteed to be in the map — lines 16-18 can never execute.

♻️ Proposed cleanup
 int StatusAggregator::clear_device(const structures::DeviceIdentification &device) {
 	if(is_device_valid(device) == NOT_OK) {
 		return DEVICE_NOT_REGISTERED;
 	}
-	if (not devices.contains(device)) {
-		return NOT_OK;
-	}
 	auto &deviceState = devices.at(device);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@source/bringauto/modules/StatusAggregator.cpp` around lines 16 - 18, The
early devices.contains(device) guard that returns NOT_OK (the block at lines
checking devices.contains before proceeding) is redundant because
is_device_valid(...) already ensures both is_device_type_supported(...) and
devices.contains(device); remove the unreachable contains check and its return,
and ensure callers rely on is_device_valid (referenced by is_device_valid and
devices.contains) so the function proceeds assuming the device is present; keep
any necessary null/lookup code that actually uses devices but delete the
redundant conditional and return NOT_OK.
include/bringauto/common_utils/EnumUtils.hpp (1)

31-41: Consider removing default to get compiler warnings on unhandled enum values.

With default: present, adding a new ProtocolType enumerator won't produce a -Wswitch warning. Removing default and keeping only the explicit INVALID case lets the compiler catch missing cases at compile time. Same applies to loggerVerbosityToString below.

Proposed change for protocolTypeToString
 	static constexpr std::string_view protocolTypeToString(structures::ProtocolType toString) {
 		switch(toString) {
 			case structures::ProtocolType::MQTT:
 				return settings::Constants::MQTT;
 			case structures::ProtocolType::DUMMY:
 				return settings::Constants::DUMMY;
 			case structures::ProtocolType::INVALID:
-			default:
 				return "";
 		}
+		return "";
 	};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@include/bringauto/common_utils/EnumUtils.hpp` around lines 31 - 41, Remove
the `default:` branch in protocolTypeToString so the switch only handles the
explicit ProtocolType enumerators (MQTT, DUMMY, INVALID) which enables compiler
-Wswitch warnings for new enum values; keep the INVALID case to return the empty
string and ensure the function remains constexpr and returns std::string_view
for all handled cases. Apply the same change to loggerVerbosityToString:
eliminate its `default:` branch and list all Verbosity enum cases explicitly so
the compiler will warn when a new verbosity value is added.
include/bringauto/modules/StatusAggregator.hpp (2)

163-185: Pass device_type by value, not by const unsigned int &, for small integral types.

const unsigned int & for device_type adds indirection without benefit — unsigned int is a register-sized type that is more efficiently passed by value. This applies to all three private helpers.

♻️ Proposed fix
-	Buffer aggregateStatus(const structures::StatusAggregatorDeviceState &deviceState,
-						   const Buffer &status,
-						   const unsigned int &device_type) const;
+	Buffer aggregateStatus(const structures::StatusAggregatorDeviceState &deviceState,
+						   const Buffer &status,
+						   unsigned int device_type) const;

-	void aggregateSetStatus(structures::StatusAggregatorDeviceState &deviceState, const Buffer &status,
-							const unsigned int &device_type) const;
+	void aggregateSetStatus(structures::StatusAggregatorDeviceState &deviceState, const Buffer &status,
+							unsigned int device_type) const;

-	void aggregateSetSendStatus(structures::StatusAggregatorDeviceState &deviceState, const Buffer &status,
-								const unsigned int &device_type) const;
+	void aggregateSetSendStatus(structures::StatusAggregatorDeviceState &deviceState, const Buffer &status,
+								unsigned int device_type) const;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@include/bringauto/modules/StatusAggregator.hpp` around lines 163 - 185,
Change the parameter type for device_type from const unsigned int & to unsigned
int (pass by value) in the three methods aggregateStatus, aggregateSetStatus,
and aggregateSetSendStatus so small integral types are passed efficiently;
update their declarations (and any corresponding definitions/implementations) to
use unsigned int device_type instead of const unsigned int &device_type and
ensure any callers still compile with the new signature.

148-151: getDeviceTimeoutCount should be const — it's a pure accessor.

This method only reads the timeout count for a device and does not modify StatusAggregator state. Marking it const would be correct and allow it to be called on const StatusAggregator instances.

♻️ Proposed fix
-	int getDeviceTimeoutCount(const structures::DeviceIdentification& device);
+	int getDeviceTimeoutCount(const structures::DeviceIdentification& device) const;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@include/bringauto/modules/StatusAggregator.hpp` around lines 148 - 151, The
method getDeviceTimeoutCount is an accessor and should be marked const: update
the declaration in StatusAggregator.hpp to int getDeviceTimeoutCount(const
structures::DeviceIdentification& device) const; and also update the
corresponding implementation/definition (e.g.,
StatusAggregator::getDeviceTimeoutCount) to be const so the signatures match;
ensure any callers expecting a non-const method still work and that you rebuild
to catch mismatches.
source/bringauto/modules/ModuleHandler.cpp (1)

172-176: Prefer .at() over operator[] for safer map access.

Line 176 uses statusAggregators[moduleNumber], which would insert a default-constructed shared_ptr<StatusAggregator> if the key were absent. The contains guard at line 172 makes an actual insertion unreachable, but .at() would be more defensive and makes the intent explicit.

♻️ Proposed fix
-	const auto statusAggregator = statusAggregators[moduleNumber];
+	const auto statusAggregator = statusAggregators.at(moduleNumber);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@source/bringauto/modules/ModuleHandler.cpp` around lines 172 - 176, Replace
the use of operator[] with a bounds-checked lookup: when retrieving the
aggregator for moduleNumber from statusAggregators (in ModuleHandler.cpp around
the usage of statusAggregators and moduleNumber), use
statusAggregators.at(moduleNumber) and assign it to a const reference (e.g.,
const auto& statusAggregator) to avoid unintended insertion and extra copies;
keep the existing contains check unchanged.
source/bringauto/settings/SettingsParser.cpp (1)

130-156: const-qualified methods that mutate state through the shared_ptr — consider removing const or documenting the intent.

fillLoggingSettings, fillInternalServerSettings, fillModulePathsSettings, and fillExternalConnectionSettings are all marked const, but each of them mutates *settings_ (the Settings object pointed to by settings_). In a const member function, the shared_ptr member itself (i.e., which Settings object it points to) cannot change, but nothing prevents mutation of the underlying object. The const qualifier therefore gives a false impression that these methods are non-modifying. Since fillSettings() (line 117, non-const) is the only caller, no API break occurs, but readers may be misled into thinking callers with const SettingsParser & can invoke these methods safely.

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

In `@source/bringauto/settings/SettingsParser.cpp` around lines 130 - 156, These
helper methods (fillLoggingSettings, fillInternalServerSettings,
fillModulePathsSettings, fillExternalConnectionSettings) are declared const but
mutate the Settings object via the shared_ptr settings_; remove the misleading
const qualifier from those member functions (or if you prefer to keep them, add
clear comments/docs stating they mutate *settings_) so callers understand they
modify state; update the declarations and definitions to be non-const (or add
documentation above each method) and run a build to fix any const-call sites
(fillSettings is already non-const so it should remain unchanged).
include/bringauto/external_client/connection/communication/DummyCommunication.hpp (1)

17-17: Constructor takes const& while the base now takes by value — move optimization is lost.

ICommunicationChannel's constructor was updated this PR to take ExternalConnectionSettings by value precisely to allow callers to move into it. DummyCommunication still takes a const&, so the base always copy-constructs the settings. For consistency with the optimization intent:

♻️ Proposed fix
-    explicit DummyCommunication(const structures::ExternalConnectionSettings &settings);
+    explicit DummyCommunication(structures::ExternalConnectionSettings settings);

And in DummyCommunication.cpp:

-DummyCommunication::DummyCommunication(const structures::ExternalConnectionSettings &settings)
-    : ICommunicationChannel(settings)
+DummyCommunication::DummyCommunication(structures::ExternalConnectionSettings settings)
+    : ICommunicationChannel(std::move(settings))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@include/bringauto/external_client/connection/communication/DummyCommunication.hpp`
at line 17, DummyCommunication's constructor currently accepts const
ExternalConnectionSettings& which prevents taking advantage of the move-friendly
ICommunicationChannel(ExternalConnectionSettings) change; update
DummyCommunication(const structures::ExternalConnectionSettings &settings) to
take the parameter by value (structures::ExternalConnectionSettings settings)
and in the implementation forward/move that parameter into the base
ICommunicationChannel constructor and any members (use std::move(settings) when
calling ICommunicationChannel(...) and assigning to members) so callers can move
settings into DummyCommunication and avoid unnecessary copies.
include/bringauto/settings/LoggerId.hpp (1)

17-28: "DEBUG" is not an explicit case — falls through silently to the default.

Since MODULE_GATEWAY_MINIMUM_LOGGER_VERBOSITY defaults to "DEBUG", the most common input is handled via the else-fallthrough rather than an explicit branch. While correct, it contradicts the doc comment's statement that the fallback is for unknown inputs, and hides intent.

♻️ Suggested explicit case
 constexpr bringauto::logging::LoggerVerbosity toLoggerVerbosity(std::string_view verbosityString) {
+    if (verbosityString == "DEBUG") {
+        return bringauto::logging::LoggerVerbosity::Debug;
+    } else if (verbosityString == "INFO") {
-    if (verbosityString == "INFO") {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@include/bringauto/settings/LoggerId.hpp` around lines 17 - 28, The
toLoggerVerbosity(std::string_view verbosityString) function currently relies on
fall-through to return LoggerVerbosity::Debug for "DEBUG" and unknown values;
add an explicit branch that checks for "DEBUG" and returns
bringauto::logging::LoggerVerbosity::Debug so the intent is clear and matches
the doc comment, keeping the existing final return as the unknown-input
fallback; update the function to include the explicit "DEBUG" case (referencing
toLoggerVerbosity and bringauto::logging::LoggerVerbosity) and leave the default
return behavior unchanged.
include/bringauto/structures/ModuleLibrary.hpp (1)

24-35: Explicit #include <unordered_map> recommended for clarity.

std::unordered_map is used at lines 24, 33, and 35. While the code compiles due to the transitive include from StatusAggregator.hpp (which includes <unordered_map>), explicitly including it in this header improves code clarity and avoids fragile implicit dependencies.

Suggested addition
 `#include` <bringauto/modules/ModuleManagerLibraryHandler.hpp>
 `#include` <bringauto/modules/StatusAggregator.hpp>

+#include <unordered_map>
 `#include` <memory>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@include/bringauto/structures/ModuleLibrary.hpp` around lines 24 - 35, Add an
explicit include for <unordered_map> in ModuleLibrary.hpp to avoid relying on
transitive includes; update the header that declares loadLibraries,
initStatusAggregators and the member maps moduleLibraryHandlers and
statusAggregators so it directly includes <unordered_map> at the top of the file
(keeping existing includes intact).
source/bringauto/external_client/connection/ExternalConnection.cpp (1)

177-197: Inconsistent map access: operator[] still used here while find() is used elsewhere.

Lines 183 and 191 still use errorAggregators_[deviceModule] directly, which default-constructs an entry if the key is absent (and invalidates iterators on unordered_map). The rest of this file was migrated to find()/end() checks. Consider applying the same pattern here for consistency and safety.

Suggested approach
+	const auto aggIt = errorAggregators_.find(deviceModule);
+	if (aggIt == errorAggregators_.end()) {
+		log::logError("Module {} not found in error aggregators", deviceModule);
+		return DEVICE_NOT_REGISTERED;
+	}
+	auto &errorAggregator = aggIt->second;
+
-	const auto &lastErrorStatusRc = errorAggregators_[deviceModule].get_error(errorBuffer, deviceIdentification);
+	const auto &lastErrorStatusRc = errorAggregator.get_error(errorBuffer, deviceIdentification);
 	...
-	const int lastStatusRc = errorAggregators_[deviceModule].get_last_status(statusBuffer, deviceIdentification);
+	const int lastStatusRc = errorAggregator.get_last_status(statusBuffer, deviceIdentification);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@source/bringauto/external_client/connection/ExternalConnection.cpp` around
lines 177 - 197, In ExternalConnection::statusMessageHandle the code uses
errorAggregators_[deviceModule] which can create a new map entry and invalidate
iterators; change to lookup via errorAggregators_.find(deviceModule), check
against end() and if missing log and return DEVICE_NOT_REGISTERED (or
appropriate error), then call get_error and get_last_status on the found
iterator's mapped value; ensure you use the iterator (e.g., it->second) for both
get_error and get_last_status to match the rest of the file's find()/end()
pattern and avoid accidental insertions.
include/bringauto/settings/LoggerWrapper.hpp (1)

34-72: if constexpr pattern doesn't fully elide the log call at compile time.

When the if constexpr branch is taken (returns early), the BaseLogger::log(...) call on the next line is still instantiated (though unreachable). An else branch or inverted condition would make the intent clearer and is more idiomatic for compile-time filtering:

if constexpr (verbosity <= logging::LoggerVerbosity::Debug) {
    BaseLogger::log(logging::LoggerVerbosity::Debug, std::forward<LogArgs>(args)...);
}

In practice, compilers optimize away the unreachable code, so this is a clarity improvement rather than a functional fix.

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

In `@include/bringauto/settings/LoggerWrapper.hpp` around lines 34 - 72, The
compile-time filtering pattern in LoggerWrapper's methods (e.g., logDebug,
logInfo, logWarning, logError, logCritical) should invert the constexpr
condition so the BaseLogger::log call is only instantiated inside the taken
branch; replace the existing "if constexpr (verbosity >
logging::LoggerVerbosity::<Level>) { return; } BaseLogger::log(...)" with "if
constexpr (verbosity <= logging::LoggerVerbosity::<Level>) {
BaseLogger::log(...); }" for each method to make intent explicit and avoid
instantiating the log call when excluded.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@include/bringauto/external_client/ExternalClient.hpp`:
- Line 82: Add a direct header include for unordered_map in ExternalClient.hpp
so the declaration of externalConnectionMap_ (std::unordered_map<unsigned int,
std::reference_wrapper<connection::ExternalConnection>>) does not rely on
transitive includes; open include list in ExternalClient.hpp and add `#include`
<unordered_map> near the other standard headers to make the dependency explicit
and prevent brittle compilation when upstream headers change.

In `@include/bringauto/internal_server/InternalServer.hpp`:
- Line 23: Fix the grammar in the comment inside InternalServer.hpp: change
"Messaged is send through queue to ModuleHandler, and when answer is given
resends it to Internal client." to a correct phrasing such as "Message is sent
through queue to ModuleHandler, and when an answer is given it is resent to the
internal client." Update the comment near the InternalServer
declaration/definition so it uses "Message" and "is sent" (and optionally add
"an" before "answer" and normalize "internal client" casing).

In `@include/bringauto/settings/LoggerWrapper.hpp`:
- Around line 33-72: Update the misleading comments and the copy-paste label in
LoggerWrapper.hpp: for each wrapper (logDebug, logInfo, logWarning, logError,
logCritical) change the comment to state that the call is skipped when the
wrapper's configured verbosity is higher than the message level (i.e., "Skip
logging if configured verbosity is higher than <Level>"), and in the dynamic
log(...) method replace the incorrect "Critical" reference with the correct
level/name used there so the comment matches the implemented check.

In `@include/bringauto/structures/Connection.hpp`:
- Around line 28-33: The remoteEndpointAddress() method currently calls
socket.is_open() and then socket.remote_endpoint(), which has a TOCTOU and can
throw boost::system::system_error; change remoteEndpointAddress() to call the
non-throwing overload remote_endpoint(error_code&) on the same socket object
(e.g., socket.remote_endpoint(ec)), check the resulting
boost::system::error_code (or empty/failed) and return the address string only
on success, otherwise return a safe "(N/A, socket is not open)" or a clear error
placeholder; keep references to remoteEndpointAddress(), socket,
remote_endpoint(), and is_open() to locate and update the method.

In `@source/bringauto/common_utils/EnumUtils.cpp`:
- Around line 13-15: The DUMMY branch in EnumUtils::toEnum (the if/else branch
checking toEnum == settings::Constants::DUMMY and returning
structures::ProtocolType::DUMMY) is indented with spaces while surrounding
branches (e.g., the MQTT branch) use tabs; replace the leading spaces with tabs
to match the file's indentation style so the DUMMY branch aligns with the other
else-if branches.

In `@source/bringauto/external_client/connection/ExternalConnection.cpp`:
- Around line 382-400: The iterator `it` returned in
ExternalConnection::fillErrorAggregator is potentially invalidated by
fillErrorAggregatorWithNotAckedStatuses because that method may use
errorAggregators_ operator[]; to fix, avoid using the possibly-invalidated
iterator: save the key (moduleNum) and after calling
fillErrorAggregatorWithNotAckedStatuses re-find the entry in errorAggregators_
(e.g., auto it = errorAggregators_.find(moduleNum) again) before accessing
it->second and calling add_status_to_error_aggregator, or alternatively replace
the operator[] usage in fillErrorAggregatorWithNotAckedStatuses with
errorAggregators_.at(...) so missing modules throw instead of inserting and
invalidating iterators; ensure you update references to it, moduleNum,
fillErrorAggregatorWithNotAckedStatuses, errorAggregators_, and
add_status_to_error_aggregator accordingly.

In `@source/bringauto/internal_server/InternalServer.cpp`:
- Around line 37-40: The code currently calls the throwing overload
connection->socket.set_option(keepAliveOption) and
connection->socket.set_option(noDelayOption) inside the async accept handler;
change these to the error_code overloads (e.g.,
connection->socket.set_option(option, boost::system::error_code ec)) and check
ec for errors, logging the failure and cleanly closing or abandoning connection
instead of allowing an exception to escape the accept lambda/run loop; update
the code paths around keepAliveOption, noDelayOption and the async accept
handler to handle and recover from non‑fatal set_option failures.

In `@source/bringauto/modules/StatusAggregator.cpp`:
- Around line 227-228: The getDeviceTimeoutCount implementation currently uses
deviceTimeouts_[device] which silently inserts missing keys; change
StatusAggregator::getDeviceTimeoutCount to use deviceTimeouts_.find(device) and
return 0 if not found (no insertion), and update the declaration/signature of
getDeviceTimeoutCount in the header to be const so the implementation can be
const-correct and compiled as a const method; ensure the header/signature
matches the new const implementation.

In `@source/bringauto/settings/SettingsParser.cpp`:
- Around line 228-230: The assignment to settingsName for ProtocolType::DUMMY is
dead because fillExternalConnectionSettings leaves protocolSettings empty and
the serialization loop that would use settingsName never runs; update the code
so settingsName is only set when protocolSettings is non-empty (e.g., check
protocolSettings or the vector used in the serialization loop before assigning
settingsName), or explicitly skip/annotate the DUMMY case in the switch for
ProtocolType::DUMMY (referencing ProtocolType::DUMMY, Constants::DUMMY,
settingsName, and fillExternalConnectionSettings) to make the intent clear and
remove the unreachable assignment.

In `@test/source/InternalServerTests.cpp`:
- Around line 532-533: Fix the typos in the comment block that begins "@brief
tests if server correctly disconnects if it does not receive response to connect
from module hanlder in itme" by changing "itme" to "time" and "hanlder" to
"handler" so the line reads "...response to connect from module handler in
time".

In `@test/source/testing_utils/TestHandler.cpp`:
- Line 305: Remove the now-unused method
insteadOfMessageExpectTimeoutThenError(): delete its declaration in
InternalClientForTesting.hpp and its implementation in
InternalClientForTesting.cpp (symbol: insteadOfMessageExpectTimeoutThenError) to
clean up dead code, and update any references if present; additionally, rename
runTestsWithModuleHandlerTimeout and its helpers runConnects and runStatuses to
names that reflect immediate error behavior (e.g.,
runTestsWithModuleHandlerError, runConnectsWithErrors, runStatusesWithErrors) so
their intent matches the client expecting an immediate error rather than a
timeout.

---

Outside diff comments:
In `@source/bringauto/modules/ModuleHandler.cpp`:
- Around line 15-21: In destroy(), the if(message.disconnected()) block declares
deviceId via message.getDeviceId() but never uses it, causing dead code and
compiler warnings; remove the unused variable and the empty if block (or replace
it with the intended cleanup call if you meant to act on deviceId), i.e., in the
loop over fromInternalQueue_ eliminate the no-op if(message.disconnected()) {
auto deviceId = message.getDeviceId(); } so only fromInternalQueue_->pop()
remains (or add the actual disconnect handling using message.getDeviceId()).

In `@source/bringauto/modules/StatusAggregator.cpp`:
- Around line 30-35: The current error path in StatusAggregator::aggregateStatus
returns a default-initialized aggregatedStatusBuff (Buffer {}) which contradicts
the log and overwrites device state; change the failure branch so that when
module_->aggregateStatus(aggregatedStatusBuff, currStatus, status, device_type)
!= OK you assign or return currStatus (the existing deviceState.getStatus())
instead of the empty aggregatedStatusBuff to preserve state — update the error
branch in aggregateStatus to set aggregatedStatusBuff = currStatus (or return
currStatus) so callers like aggregateSetStatus and aggregateSetSendStatus do not
receive and propagate an empty Buffer.

---

Duplicate comments:
In `@include/bringauto/modules/ModuleHandler.hpp`:
- Around line 34-97: Several methods in ModuleHandler.hpp are marked const but
visibly mutate shared state (e.g., dereferencing shared_ptrs/references); remove
the const qualifier from any method that performs observable mutations: run(),
destroy(), handleMessages(), checkTimeoutedMessages(), handleDisconnect(),
sendAggregatedStatus(), handleConnect(), sendConnectResponse(), handleStatus(),
and checkExternalQueueSize(). Update the method declarations in the header and
the corresponding definitions in the implementation file to drop the trailing
const, and adjust any callers or tests if they relied on the const signature;
alternatively, if you truly need a const method, make the mutated member(s)
mutable and document the narrower "logical const" guarantee—choose one approach
and apply it consistently for the listed methods.

---

Nitpick comments:
In `@include/bringauto/common_utils/EnumUtils.hpp`:
- Around line 31-41: Remove the `default:` branch in protocolTypeToString so the
switch only handles the explicit ProtocolType enumerators (MQTT, DUMMY, INVALID)
which enables compiler -Wswitch warnings for new enum values; keep the INVALID
case to return the empty string and ensure the function remains constexpr and
returns std::string_view for all handled cases. Apply the same change to
loggerVerbosityToString: eliminate its `default:` branch and list all Verbosity
enum cases explicitly so the compiler will warn when a new verbosity value is
added.

In
`@include/bringauto/external_client/connection/communication/DummyCommunication.hpp`:
- Line 17: DummyCommunication's constructor currently accepts const
ExternalConnectionSettings& which prevents taking advantage of the move-friendly
ICommunicationChannel(ExternalConnectionSettings) change; update
DummyCommunication(const structures::ExternalConnectionSettings &settings) to
take the parameter by value (structures::ExternalConnectionSettings settings)
and in the implementation forward/move that parameter into the base
ICommunicationChannel constructor and any members (use std::move(settings) when
calling ICommunicationChannel(...) and assigning to members) so callers can move
settings into DummyCommunication and avoid unnecessary copies.

In
`@include/bringauto/external_client/connection/messages/SentMessagesHandler.hpp`:
- Line 68: The method declaration for isDeviceConnected should match the const
and [[nodiscard]] qualifiers used by its sibling predicate isAnyDeviceConnected:
update the declaration of isDeviceConnected(const
structures::DeviceIdentification &device) to [[nodiscard]] bool
isDeviceConnected(const structures::DeviceIdentification &device) const; so the
method is marked as a non-mutating, nodiscard query (and update any
corresponding definition/implementation of
SentMessagesHandler::isDeviceConnected to include the trailing const).

In `@include/bringauto/modules/StatusAggregator.hpp`:
- Around line 163-185: Change the parameter type for device_type from const
unsigned int & to unsigned int (pass by value) in the three methods
aggregateStatus, aggregateSetStatus, and aggregateSetSendStatus so small
integral types are passed efficiently; update their declarations (and any
corresponding definitions/implementations) to use unsigned int device_type
instead of const unsigned int &device_type and ensure any callers still compile
with the new signature.
- Around line 148-151: The method getDeviceTimeoutCount is an accessor and
should be marked const: update the declaration in StatusAggregator.hpp to int
getDeviceTimeoutCount(const structures::DeviceIdentification& device) const; and
also update the corresponding implementation/definition (e.g.,
StatusAggregator::getDeviceTimeoutCount) to be const so the signatures match;
ensure any callers expecting a non-const method still work and that you rebuild
to catch mismatches.

In `@include/bringauto/settings/LoggerId.hpp`:
- Around line 17-28: The toLoggerVerbosity(std::string_view verbosityString)
function currently relies on fall-through to return LoggerVerbosity::Debug for
"DEBUG" and unknown values; add an explicit branch that checks for "DEBUG" and
returns bringauto::logging::LoggerVerbosity::Debug so the intent is clear and
matches the doc comment, keeping the existing final return as the unknown-input
fallback; update the function to include the explicit "DEBUG" case (referencing
toLoggerVerbosity and bringauto::logging::LoggerVerbosity) and leave the default
return behavior unchanged.

In `@include/bringauto/settings/LoggerWrapper.hpp`:
- Around line 34-72: The compile-time filtering pattern in LoggerWrapper's
methods (e.g., logDebug, logInfo, logWarning, logError, logCritical) should
invert the constexpr condition so the BaseLogger::log call is only instantiated
inside the taken branch; replace the existing "if constexpr (verbosity >
logging::LoggerVerbosity::<Level>) { return; } BaseLogger::log(...)" with "if
constexpr (verbosity <= logging::LoggerVerbosity::<Level>) {
BaseLogger::log(...); }" for each method to make intent explicit and avoid
instantiating the log call when excluded.

In `@include/bringauto/structures/ModuleLibrary.hpp`:
- Around line 24-35: Add an explicit include for <unordered_map> in
ModuleLibrary.hpp to avoid relying on transitive includes; update the header
that declares loadLibraries, initStatusAggregators and the member maps
moduleLibraryHandlers and statusAggregators so it directly includes
<unordered_map> at the top of the file (keeping existing includes intact).

In
`@source/bringauto/external_client/connection/communication/MqttCommunication.cpp`:
- Around line 63-71: The change to MqttCommunication::initializeConnection
altered the branch from "else if (client_ != nullptr)" to a standalone "if
(client_ != nullptr)" which is functionally equivalent but less explicitly
signaling mutual exclusivity with the earlier early-return; restore the original
"else if (client_ != nullptr)" (or add a brief clarifying comment above the
early-return) so the intent that the connected case is mutually exclusive with
the disconnected-but-existing case is clear when reading the code; ensure
references to client_, client_->is_connected(), closeConnection(), and connect()
remain unchanged.

In `@source/bringauto/external_client/connection/ExternalConnection.cpp`:
- Around line 177-197: In ExternalConnection::statusMessageHandle the code uses
errorAggregators_[deviceModule] which can create a new map entry and invalidate
iterators; change to lookup via errorAggregators_.find(deviceModule), check
against end() and if missing log and return DEVICE_NOT_REGISTERED (or
appropriate error), then call get_error and get_last_status on the found
iterator's mapped value; ensure you use the iterator (e.g., it->second) for both
get_error and get_last_status to match the rest of the file's find()/end()
pattern and avoid accidental insertions.

In `@source/bringauto/modules/ModuleHandler.cpp`:
- Around line 172-176: Replace the use of operator[] with a bounds-checked
lookup: when retrieving the aggregator for moduleNumber from statusAggregators
(in ModuleHandler.cpp around the usage of statusAggregators and moduleNumber),
use statusAggregators.at(moduleNumber) and assign it to a const reference (e.g.,
const auto& statusAggregator) to avoid unintended insertion and extra copies;
keep the existing contains check unchanged.

In `@source/bringauto/modules/StatusAggregator.cpp`:
- Around line 16-18: The early devices.contains(device) guard that returns
NOT_OK (the block at lines checking devices.contains before proceeding) is
redundant because is_device_valid(...) already ensures both
is_device_type_supported(...) and devices.contains(device); remove the
unreachable contains check and its return, and ensure callers rely on
is_device_valid (referenced by is_device_valid and devices.contains) so the
function proceeds assuming the device is present; keep any necessary null/lookup
code that actually uses devices but delete the redundant conditional and return
NOT_OK.

In `@source/bringauto/settings/SettingsParser.cpp`:
- Around line 130-156: These helper methods (fillLoggingSettings,
fillInternalServerSettings, fillModulePathsSettings,
fillExternalConnectionSettings) are declared const but mutate the Settings
object via the shared_ptr settings_; remove the misleading const qualifier from
those member functions (or if you prefer to keep them, add clear comments/docs
stating they mutate *settings_) so callers understand they modify state; update
the declarations and definitions to be non-const (or add documentation above
each method) and run a build to fix any const-call sites (fillSettings is
already non-const so it should remain unchanged).

* - map is needed because of the possibility of multiple modules connected to one external server
*/
std::map<unsigned int, std::reference_wrapper<connection::ExternalConnection>> externalConnectionMap_ {};
std::unordered_map<unsigned int, std::reference_wrapper<connection::ExternalConnection>> externalConnectionMap_ {};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find and examine ExternalClient.hpp
echo "=== ExternalClient.hpp location ==="
fd 'ExternalClient\.hpp$'

echo ""
echo "=== Current includes in ExternalClient.hpp ==="
fd 'ExternalClient\.hpp$' -x cat -n {} | head -30

echo ""
echo "=== Check for unordered_map around line 82 ==="
fd 'ExternalClient\.hpp$' -x sed -n '75,90p' {}

Repository: bringauto/module-gateway

Length of output: 2267


🏁 Script executed:

#!/bin/bash
# Check ExternalConnection.hpp for unordered_map
echo "=== ExternalConnection.hpp location ==="
fd 'ExternalConnection\.hpp$'

echo ""
echo "=== Check if unordered_map is in ExternalConnection.hpp ==="
fd 'ExternalConnection\.hpp$' -x rg -n 'unordered_map|#include.*unordered' {}

Repository: bringauto/module-gateway

Length of output: 313


🏁 Script executed:

#!/bin/bash
# Check if ExternalConnection.hpp includes unordered_map
echo "=== First 30 lines of ExternalConnection.hpp ==="
fd 'ExternalConnection\.hpp$' -x head -30 {}

Repository: bringauto/module-gateway

Length of output: 1377


🏁 Script executed:

#!/bin/bash
# Check all includes in ExternalConnection.hpp
echo "=== All includes in ExternalConnection.hpp ==="
fd 'ExternalConnection\.hpp$' -x sed -n '1,20p' {}

Repository: bringauto/module-gateway

Length of output: 854


🏁 Script executed:

#!/bin/bash
# Check ErrorAggregator.hpp since it's used as value type in ExternalConnection's unordered_map
echo "=== ErrorAggregator.hpp includes (first 30 lines) ==="
fd 'ErrorAggregator\.hpp$' -x head -30 {}

Repository: bringauto/module-gateway

Length of output: 842


Add missing #include <unordered_map> to ExternalClient.hpp.

externalConnectionMap_ at line 82 uses std::unordered_map, but the header lacks an explicit #include <unordered_map>. Currently, the code compiles via a transitive include through ExternalConnection.hppErrorAggregator.hpp, but this is fragile. If any upstream header is refactored, compilation will break. Add the include directly.

Suggested fix
 `#include` <memory>
 `#include` <vector>
 `#include` <list>
+#include <unordered_map>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
std::unordered_map<unsigned int, std::reference_wrapper<connection::ExternalConnection>> externalConnectionMap_ {};
`#include` <memory>
`#include` <vector>
`#include` <list>
`#include` <unordered_map>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@include/bringauto/external_client/ExternalClient.hpp` at line 82, Add a
direct header include for unordered_map in ExternalClient.hpp so the declaration
of externalConnectionMap_ (std::unordered_map<unsigned int,
std::reference_wrapper<connection::ExternalConnection>>) does not rely on
transitive includes; open include list in ExternalClient.hpp and add `#include`
<unordered_map> near the other standard headers to make the dependency explicit
and prevent brittle compilation when upstream headers change.

* Header's format is 32 bit unsigned int with little endian endianness.
* Header represents size of the remaining part of the message.
* Messaged is send thru queue to ModuleHandler, and when answer is given resends it to Internal client.
* Messaged is send through queue to ModuleHandler, and when answer is given resends it to Internal client.
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Grammar errors in changed comment: "Messaged is send" → "Message is sent".

This line has two typos: "Messaged" should be "Message" and "is send" should be "is sent".

📝 Proposed fix
- * Messaged is send through queue to ModuleHandler, and when answer is given resends it to Internal client.
+ * Message is sent through queue to ModuleHandler, and when answer is given resent to Internal client.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
* Messaged is send through queue to ModuleHandler, and when answer is given resends it to Internal client.
* Message is sent through queue to ModuleHandler, and when answer is given resent to Internal client.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@include/bringauto/internal_server/InternalServer.hpp` at line 23, Fix the
grammar in the comment inside InternalServer.hpp: change "Messaged is send
through queue to ModuleHandler, and when answer is given resends it to Internal
client." to a correct phrasing such as "Message is sent through queue to
ModuleHandler, and when an answer is given it is resent to the internal client."
Update the comment near the InternalServer declaration/definition so it uses
"Message" and "is sent" (and optionally add "an" before "answer" and normalize
"internal client" casing).

Comment on lines +33 to +72
// wrappers for common log levels
template <typename... LogArgs>
static void logDebug(LogArgs &&...args) {
if constexpr (verbosity > logging::LoggerVerbosity::Debug) {
return; // Skip logging if verbosity is lower than Debug
}
BaseLogger::log(logging::LoggerVerbosity::Debug, std::forward<LogArgs>(args)...);
}

template <typename... LogArgs>
static void logInfo(LogArgs &&...args) {
if constexpr (verbosity > logging::LoggerVerbosity::Info) {
return; // Skip logging if verbosity is lower than Info
}
BaseLogger::log(logging::LoggerVerbosity::Info, std::forward<LogArgs>(args)...);
}

template <typename... LogArgs>
static void logWarning(LogArgs &&...args) {
if constexpr (verbosity > logging::LoggerVerbosity::Warning) {
return; // Skip logging if verbosity is lower than Warning
}
BaseLogger::log(logging::LoggerVerbosity::Warning, std::forward<LogArgs>(args)...);
}

template <typename... LogArgs>
static void logError(LogArgs &&...args) {
if constexpr (verbosity > logging::LoggerVerbosity::Error) {
return; // Skip logging if verbosity is lower than Error
}
BaseLogger::log(logging::LoggerVerbosity::Error, std::forward<LogArgs>(args)...);
}

template <typename... LogArgs>
static void logCritical(LogArgs &&...args) {
if constexpr (verbosity > logging::LoggerVerbosity::Critical) {
return; // Skip logging if verbosity is lower than Critical
}
BaseLogger::log(logging::LoggerVerbosity::Critical, std::forward<LogArgs>(args)...);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Misleading comments on verbosity filtering direction.

The comments say "Skip logging if verbosity is lower than X" but the logic does the opposite: it skips when the wrapper's minimum verbosity is higher than the message level. Additionally, line 77 is a copy-paste error referencing "Critical" in the dynamic log() method.

Suggested comment fix
 	template <typename... LogArgs>
 	static void logDebug(LogArgs &&...args) {
 		if constexpr (verbosity > logging::LoggerVerbosity::Debug) {
-			return; // Skip logging if verbosity is lower than Debug
+			return; // Skip: minimum verbosity exceeds Debug level
 		}
 		BaseLogger::log(logging::LoggerVerbosity::Debug, std::forward<LogArgs>(args)...);
 	}

Apply the same pattern to logInfo, logWarning, logError, logCritical, and fix line 77:

 	template <typename... LogArgs>
 	static void log(logging::LoggerVerbosity dynVerbosity, LogArgs &&...args) {
 		if (verbosity > dynVerbosity) {
-			return; // Skip logging if verbosity is lower than Critical
+			return; // Skip: dynamic verbosity is below the minimum threshold
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@include/bringauto/settings/LoggerWrapper.hpp` around lines 33 - 72, Update
the misleading comments and the copy-paste label in LoggerWrapper.hpp: for each
wrapper (logDebug, logInfo, logWarning, logError, logCritical) change the
comment to state that the call is skipped when the wrapper's configured
verbosity is higher than the message level (i.e., "Skip logging if configured
verbosity is higher than <Level>"), and in the dynamic log(...) method replace
the incorrect "Critical" reference with the correct level/name used there so the
comment matches the implemented check.

Comment on lines +28 to +33
std::string remoteEndpointAddress() const {
if (!socket.is_open()) {
return "(N/A, socket is not open)";
}
return socket.remote_endpoint().address().to_string();
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

boost::asio::ip::tcp socket remote_endpoint error_code non-throwing overload documentation

💡 Result:

boost::asio::ip::tcp::socket inherits remote_endpoint() from boost::asio::basic_stream_socket / basic_socket, which provides two overloads:

  • Throwing overload (throws boost::system::system_error on failure):

  • Non-throwing overload (reports failure via error_code):

    • endpoint_type remote_endpoint(boost::system::error_code& ec) const;
    • On error, it sets ec and returns a default-constructed endpoint. (live.boost.org)

Citations:


🏁 Script executed:

# Locate and inspect the Connection.hpp file to understand the socket type and includes
fd "Connection.hpp" --type f

Repository: bringauto/module-gateway

Length of output: 179


🏁 Script executed:

# Check the actual code structure and includes around the method
cat -n include/bringauto/structures/Connection.hpp | head -50

Repository: bringauto/module-gateway

Length of output: 1668


🏁 Script executed:

# Check the full Connection.hpp file to see all includes
wc -l include/bringauto/structures/Connection.hpp

Repository: bringauto/module-gateway

Length of output: 114


🏁 Script executed:

# View the entire Connection.hpp file with focus on includes
cat include/bringauto/structures/Connection.hpp

Repository: bringauto/module-gateway

Length of output: 2015


🏁 Script executed:

# Check if std::string is available from boost/asio.hpp includes transitively
# by looking at what boost/asio.hpp includes
rg "include.*string" include/bringauto/structures/ -A 2 -B 2

Repository: bringauto/module-gateway

Length of output: 773


remote_endpoint() can throw even when is_open() returns true.

There's a TOCTOU race between is_open() and remote_endpoint() — the peer can disconnect between the two calls, causing remote_endpoint() to throw boost::system::system_error. Since this method is used in logging paths, an uncaught exception here could be disruptive. Use the non-throwing overload that accepts boost::system::error_code.

Proposed fix using the non-throwing overload
 	[[nodiscard]]
 	std::string remoteEndpointAddress() const {
-		if (!socket.is_open()) {
-			return "(N/A, socket is not open)";
-		}
-		return socket.remote_endpoint().address().to_string();
+		boost::system::error_code ec;
+		auto endpoint = socket.remote_endpoint(ec);
+		if (ec) {
+			return "(N/A, socket is not open)";
+		}
+		return endpoint.address().to_string();
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
std::string remoteEndpointAddress() const {
if (!socket.is_open()) {
return "(N/A, socket is not open)";
}
return socket.remote_endpoint().address().to_string();
}
std::string remoteEndpointAddress() const {
boost::system::error_code ec;
auto endpoint = socket.remote_endpoint(ec);
if (ec) {
return "(N/A, socket is not open)";
}
return endpoint.address().to_string();
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@include/bringauto/structures/Connection.hpp` around lines 28 - 33, The
remoteEndpointAddress() method currently calls socket.is_open() and then
socket.remote_endpoint(), which has a TOCTOU and can throw
boost::system::system_error; change remoteEndpointAddress() to call the
non-throwing overload remote_endpoint(error_code&) on the same socket object
(e.g., socket.remote_endpoint(ec)), check the resulting
boost::system::error_code (or empty/failed) and return the address string only
on success, otherwise return a safe "(N/A, socket is not open)" or a clear error
placeholder; keep references to remoteEndpointAddress(), socket,
remote_endpoint(), and is_open() to locate and update the method.

Comment on lines +13 to +15
} else if(toEnum == settings::Constants::DUMMY) {
return structures::ProtocolType::DUMMY;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Indentation inconsistency: use tabs to match the surrounding code.

Lines 13–15 use spaces for indentation while the rest of the file (e.g., the MQTT branch at lines 11–12) uses tabs.

🔧 Proposed fix
-	} else if(toEnum == settings::Constants::DUMMY) {
-        return structures::ProtocolType::DUMMY;
-    }
+	} else if(toEnum == settings::Constants::DUMMY) {
+		return structures::ProtocolType::DUMMY;
+	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} else if(toEnum == settings::Constants::DUMMY) {
return structures::ProtocolType::DUMMY;
}
} else if(toEnum == settings::Constants::DUMMY) {
return structures::ProtocolType::DUMMY;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@source/bringauto/common_utils/EnumUtils.cpp` around lines 13 - 15, The DUMMY
branch in EnumUtils::toEnum (the if/else branch checking toEnum ==
settings::Constants::DUMMY and returning structures::ProtocolType::DUMMY) is
indented with spaces while surrounding branches (e.g., the MQTT branch) use
tabs; replace the leading spaces with tabs to match the file's indentation style
so the DUMMY branch aligns with the other else-if branches.

Comment on lines +37 to +40
const boost::asio::socket_base::keep_alive keepAliveOption(true);
connection->socket.set_option(keepAliveOption);
const boost::asio::ip::tcp::no_delay noDelayOption(true);
connection->socket.set_option(noDelayOption);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

set_option uses the throwing overload — an exception inside the async handler would propagate to io_context::run().

Both keep_alive and the new no_delay options use socket.set_option(option) (the throwing overload). A boost::system::system_error thrown here would escape the async accept lambda and propagate to io_context::run(), crashing the server loop. Consider using the error_code overload to handle failures gracefully:

🛡️ Proposed fix
-		const boost::asio::socket_base::keep_alive keepAliveOption(true);
-		connection->socket.set_option(keepAliveOption);
-		const boost::asio::ip::tcp::no_delay noDelayOption(true);
-		connection->socket.set_option(noDelayOption);
+		boost::system::error_code optErr;
+		connection->socket.set_option(boost::asio::socket_base::keep_alive(true), optErr);
+		if(optErr) {
+			log::logWarning("Failed to set keep_alive on socket: {}", optErr.message());
+		}
+		connection->socket.set_option(boost::asio::ip::tcp::no_delay(true), optErr);
+		if(optErr) {
+			log::logWarning("Failed to set no_delay on socket: {}", optErr.message());
+		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const boost::asio::socket_base::keep_alive keepAliveOption(true);
connection->socket.set_option(keepAliveOption);
const boost::asio::ip::tcp::no_delay noDelayOption(true);
connection->socket.set_option(noDelayOption);
boost::system::error_code optErr;
connection->socket.set_option(boost::asio::socket_base::keep_alive(true), optErr);
if(optErr) {
log::logWarning("Failed to set keep_alive on socket: {}", optErr.message());
}
connection->socket.set_option(boost::asio::ip::tcp::no_delay(true), optErr);
if(optErr) {
log::logWarning("Failed to set no_delay on socket: {}", optErr.message());
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@source/bringauto/internal_server/InternalServer.cpp` around lines 37 - 40,
The code currently calls the throwing overload
connection->socket.set_option(keepAliveOption) and
connection->socket.set_option(noDelayOption) inside the async accept handler;
change these to the error_code overloads (e.g.,
connection->socket.set_option(option, boost::system::error_code ec)) and check
ec for errors, logging the failure and cleanly closing or abandoning connection
instead of allowing an exception to escape the accept lambda/run loop; update
the code paths around keepAliveOption, noDelayOption and the async accept
handler to handle and recover from non‑fatal set_option failures.

Comment on lines +227 to +228
int StatusAggregator::getDeviceTimeoutCount(const structures::DeviceIdentification &device) {
return deviceTimeouts_[device];
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find StatusAggregator header files
fd -e hpp -e h "StatusAggregator"

Repository: bringauto/module-gateway

Length of output: 214


🏁 Script executed:

#!/bin/bash
# Read the StatusAggregator header to find deviceTimeouts_ declaration
cat -n include/bringauto/modules/StatusAggregator.hpp | grep -A 5 -B 5 "deviceTimeouts_"

Repository: bringauto/module-gateway

Length of output: 485


🏁 Script executed:

#!/bin/bash
# Read the full StatusAggregator header
wc -l include/bringauto/modules/StatusAggregator.hpp

Repository: bringauto/module-gateway

Length of output: 118


🏁 Script executed:

#!/bin/bash
# Read the entire header file
cat -n include/bringauto/modules/StatusAggregator.hpp

Repository: bringauto/module-gateway

Length of output: 7509


🏁 Script executed:

#!/bin/bash
# Read the implementation of getDeviceTimeoutCount in the cpp file
cat -n source/bringauto/modules/StatusAggregator.cpp | sed -n '220,235p'

Repository: bringauto/module-gateway

Length of output: 424


🏁 Script executed:

#!/bin/bash
# Check for all usages of getDeviceTimeoutCount to verify const-ness is feasible
rg "getDeviceTimeoutCount" --type cpp --type hpp

Repository: bringauto/module-gateway

Length of output: 95


🏁 Script executed:

#!/bin/bash
# Check for all usages of getDeviceTimeoutCount
rg "getDeviceTimeoutCount"

Repository: bringauto/module-gateway

Length of output: 480


🏁 Script executed:

#!/bin/bash
# Check the context around the usage in ModuleHandler.cpp
rg -B 3 -A 3 "getDeviceTimeoutCount" source/bringauto/modules/ModuleHandler.cpp

Repository: bringauto/module-gateway

Length of output: 424


Use find() to avoid silent insertion of phantom timeout entries.

operator[] on deviceTimeouts_ has a write side-effect: accessing a missing device inserts it with a default value of 0, polluting the map with entries for devices that have never timed out. This prevents making the method const.

Proposed fix
-int StatusAggregator::getDeviceTimeoutCount(const structures::DeviceIdentification &device) {
-	return deviceTimeouts_[device];
+int StatusAggregator::getDeviceTimeoutCount(const structures::DeviceIdentification &device) const {
+	const auto it = deviceTimeouts_.find(device);
+	return it != deviceTimeouts_.end() ? it->second : 0;
 }

Update the declaration in StatusAggregator.hpp line 151 to add const as well.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
int StatusAggregator::getDeviceTimeoutCount(const structures::DeviceIdentification &device) {
return deviceTimeouts_[device];
int StatusAggregator::getDeviceTimeoutCount(const structures::DeviceIdentification &device) const {
const auto it = deviceTimeouts_.find(device);
return it != deviceTimeouts_.end() ? it->second : 0;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@source/bringauto/modules/StatusAggregator.cpp` around lines 227 - 228, The
getDeviceTimeoutCount implementation currently uses deviceTimeouts_[device]
which silently inserts missing keys; change
StatusAggregator::getDeviceTimeoutCount to use deviceTimeouts_.find(device) and
return 0 if not found (no insertion), and update the declaration/signature of
getDeviceTimeoutCount in the header to be const so the implementation can be
const-correct and compiled as a const method; ensure the header/signature
matches the new const implementation.

Comment on lines +228 to +230
case structures::ProtocolType::DUMMY:
settingsName = std::string(Constants::DUMMY);
break;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

DUMMY settingsName assignment is dead code in the serialization loop.

For a DUMMY endpoint, protocolSettings is never populated (the fillExternalConnectionSettings DUMMY case at lines 173–174 does nothing). The subsequent loop (line 235) therefore never executes, making settingsName = std::string(Constants::DUMMY) unreachable in practice. Consider setting settingsName only when there are actual settings to serialize, or explicitly comment that DUMMY has no settings.

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

In `@source/bringauto/settings/SettingsParser.cpp` around lines 228 - 230, The
assignment to settingsName for ProtocolType::DUMMY is dead because
fillExternalConnectionSettings leaves protocolSettings empty and the
serialization loop that would use settingsName never runs; update the code so
settingsName is only set when protocolSettings is non-empty (e.g., check
protocolSettings or the vector used in the serialization loop before assigning
settingsName), or explicitly skip/annotate the DUMMY case in the switch for
ProtocolType::DUMMY (referencing ProtocolType::DUMMY, Constants::DUMMY,
settingsName, and fillExternalConnectionSettings) to make the intent clear and
remove the unreachable assignment.

Comment on lines 532 to +533
/**
* @brief tests if server correctly timeouts then disconnects if it does not receive response to connect from module hanlder in itme
* @brief tests if server correctly disconnects if it does not receive response to connect from module hanlder in itme
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Typo: "itme" → "time".

Line 533: "in itme" should be "in time".

Proposed fix
- * `@brief` tests if server correctly disconnects if it does not receive response to connect from module hanlder in itme
+ * `@brief` tests if server correctly disconnects if it does not receive response to connect from module handler in time

Note: "hanlder" → "handler" on the same line.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* @brief tests if server correctly timeouts then disconnects if it does not receive response to connect from module hanlder in itme
* @brief tests if server correctly disconnects if it does not receive response to connect from module hanlder in itme
/**
* `@brief` tests if server correctly disconnects if it does not receive response to connect from module handler in time
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/source/InternalServerTests.cpp` around lines 532 - 533, Fix the typos in
the comment block that begins "@brief tests if server correctly disconnects if
it does not receive response to connect from module hanlder in itme" by changing
"itme" to "time" and "hanlder" to "handler" so the line reads "...response to
connect from module handler in time".

clients[i].connectSocket();
clients[i].sendMessage(connects[i]);
clients[i].insteadOfMessageExpectTimeoutThenError();
clients[i].insteadOfMessageExpectError();
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify insteadOfMessageExpectError() is declared/defined on the client type
# and confirm insteadOfMessageExpectTimeoutThenError() is fully removed.

echo "=== Declaration of insteadOfMessageExpectError ==="
rg -n --type=cpp --type=hpp -A2 'insteadOfMessageExpectError'

echo ""
echo "=== Any remaining references to insteadOfMessageExpectTimeoutThenError ==="
rg -n 'insteadOfMessageExpectTimeoutThenError'

echo ""
echo "=== All callers of runTestsWithModuleHandlerTimeout ==="
rg -n --type=cpp --type=hpp -B2 -A2 'runTestsWithModuleHandlerTimeout'

Repository: bringauto/module-gateway

Length of output: 556


🏁 Script executed:

#!/bin/bash
echo "=== All methods starting with 'insteadOf' in InternalClientForTesting ==="
rg -n 'insteadOf' test/include/testing_utils/InternalClientForTesting.hpp

echo ""
echo "=== Content of InternalClientForTesting.hpp (client interface) ==="
cat test/include/testing_utils/InternalClientForTesting.hpp

echo ""
echo "=== Search for insteadOfMessageExpectError in all files ==="
find . -type f \( -name "*.cpp" -o -name "*.hpp" -o -name "*.h" \) -exec grep -l "insteadOfMessageExpectError" {} \;

Repository: bringauto/module-gateway

Length of output: 1650


🏁 Script executed:

#!/bin/bash
echo "=== Implementations of both methods ==="
rg -n -A10 'void ClientForTesting::insteadOfMessage' test/source/testing_utils/InternalClientForTesting.cpp

echo ""
echo "=== Context around runTestsWithModuleHandlerTimeout ==="
rg -n -B5 -A15 'runTestsWithModuleHandlerTimeout' test/source/testing_utils/TestHandler.cpp

echo ""
echo "=== TestHandler::runConnects and runStatuses methods ==="
sed -n '299,343p' test/source/testing_utils/TestHandler.cpp

Repository: bringauto/module-gateway

Length of output: 3698


🏁 Script executed:

#!/bin/bash
echo "=== Full implementation of insteadOfMessageExpectError ==="
sed -n '99,118p' test/source/testing_utils/InternalClientForTesting.cpp

echo ""
echo "=== Full implementation of insteadOfMessageExpectTimeoutThenError ==="
sed -n '119,145p' test/source/testing_utils/InternalClientForTesting.cpp

Repository: bringauto/module-gateway

Length of output: 1417


🏁 Script executed:

#!/bin/bash
echo "=== All uses of insteadOfMessageExpectTimeoutThenError ==="
rg -n 'insteadOfMessageExpectTimeoutThenError' test/

echo ""
echo "=== All uses of insteadOfMessageExpectError ==="
rg -n 'insteadOfMessageExpectError' test/ | grep -v 'insteadOfMessageExpectTimeoutThenError'

Repository: bringauto/module-gateway

Length of output: 980


Remove the dead code method insteadOfMessageExpectTimeoutThenError() that is no longer called.

The method insteadOfMessageExpectError() is properly defined and correctly used at lines 305 and 335. However, the previous method insteadOfMessageExpectTimeoutThenError() now remains unused in both the declaration (test/include/testing_utils/InternalClientForTesting.hpp:42) and implementation (test/source/testing_utils/InternalClientForTesting.cpp:119). Remove both occurrences as cleanup.

Additionally, consider renaming runTestsWithModuleHandlerTimeout() and its helper methods runConnects(numberOfErrors) and runStatuses(numberOfErrors) to better reflect the updated behavior where the client no longer observes the server-side timeout phase. The current naming suggests a timeout-based test, but the client now expects an immediate error response.

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

In `@test/source/testing_utils/TestHandler.cpp` at line 305, Remove the now-unused
method insteadOfMessageExpectTimeoutThenError(): delete its declaration in
InternalClientForTesting.hpp and its implementation in
InternalClientForTesting.cpp (symbol: insteadOfMessageExpectTimeoutThenError) to
clean up dead code, and update any references if present; additionally, rename
runTestsWithModuleHandlerTimeout and its helpers runConnects and runStatuses to
names that reflect immediate error behavior (e.g.,
runTestsWithModuleHandlerError, runConnectsWithErrors, runStatusesWithErrors) so
their intent matches the client expecting an immediate error rather than a
timeout.

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

Comments