dbus-sensors: apply non-blocking discovery patch Resolve an infinite discovery loop issue where missing resources (returning 404 Not Found) would block the daemon from completing discovery and creating D-Bus sensors. Implement a "Non-Blocking Discovery with Background Retry" strategy: 1. Skip failed metric report paths during the main discovery pass to allow other working resources to be processed. 2. Store failed paths in a set and allow discovery to complete. 3. In the main polling loop, periodically (every 60 ticks) retry one failed path in the background. 4. If a retry succeeds after discovery is done, dynamically add the new sensors to D-Bus. Tested: https://paste.googleplex.com/5905898336813056?raw Platforms-Affected: Global Fusion-Link: fusion2, n/a Google-Bug-Id: 527716739 Change-Id: I61250870374afe83fd85d6112d72a89f24c97678 Signed-off-by: Chunk Huang <chunkh@google.com>
diff --git a/recipes-phosphor/sensors/dbus-sensors/0106-RedfishSensor-Implement-non-blocking-discovery-and-b.patch b/recipes-phosphor/sensors/dbus-sensors/0106-RedfishSensor-Implement-non-blocking-discovery-and-b.patch new file mode 100644 index 0000000..7f1f2f8 --- /dev/null +++ b/recipes-phosphor/sensors/dbus-sensors/0106-RedfishSensor-Implement-non-blocking-discovery-and-b.patch
@@ -0,0 +1,211 @@ +From 179e5cae7a3536e1f1e43dcae5270b4fd7c0f73e Mon Sep 17 00:00:00 2001 +From: Chunk Huang <chunkh@google.com> +Date: Tue, 7 Jul 2026 09:21:54 +0000 +Subject: [PATCH] RedfishSensor: Implement non-blocking discovery and + background retry + +Resolve an infinite discovery loop issue where missing resources +(returning 404 Not Found) would block the daemon from completing +discovery and creating D-Bus sensors. + +Implement a "Non-Blocking Discovery with Background Retry" strategy: +1. Skip failed metric report paths during the main discovery pass to + allow other working resources to be processed. +2. Store failed paths in a set and allow discovery to complete. +3. In the main polling loop, periodically (every 60 ticks) retry one + failed path in the background. +4. If a retry succeeds after discovery is done, dynamically add the + new sensors to D-Bus. + +Tested: https://paste.googleplex.com/5905898336813056?raw +Platforms-Affected: Global +Fusion-Link: fusion2, n/a +Google-Bug-Id: 527716739 +Signed-off-by: Chunk Huang <chunkh@google.com> +--- + meson.options | 1 + + src/RedfishSensor.cpp | 31 +++++++++++++++----- + src/RedfishSensor.hpp | 7 +++++ + src/RedfishSensorQuery.cpp | 58 +++++++++++++++++++++++++++++++++++++- + src/meson.build | 1 + + 5 files changed, 90 insertions(+), 8 deletions(-) + +diff --git a/meson.options b/meson.options +index 2d96c0a..e6f4511 100644 +--- a/meson.options ++++ b/meson.options +@@ -11,6 +11,7 @@ option('nvme', type: 'feature', value: 'enabled', description: 'Enable NVMe sens + option('psu', type: 'feature', value: 'enabled', description: 'Enable PSU sensor.',) + option('external', type: 'feature', value: 'enabled', description: 'Enable External sensor.',) + option('redfish', type: 'feature', value: 'enabled', description: 'Enable Redfish sensor.',) ++option('redfish-retry-ticks-threshold', type: 'integer', value: 60, description: 'Number of ticks to wait before retrying failed Redfish queries in background.') + option('tests', type: 'feature', value: 'enabled', description: 'Build tests.',) + option('validate-unsecure-feature', type : 'feature', value : 'disabled', description : 'Enables unsecure features required by validation. Note: mustbe turned off for production images.',) + option('insecure-sensor-override', type : 'feature', value : 'disabled', description : 'Enables Sensor override feature without any check.',) +diff --git a/src/RedfishSensor.cpp b/src/RedfishSensor.cpp +index b2f08d4..96addce 100644 +--- a/src/RedfishSensor.cpp ++++ b/src/RedfishSensor.cpp +@@ -401,6 +401,24 @@ void RedfishServer::nextAction() + return; + } + ++ // --- Background Retry Logic --- ++ if (!failedMetricReports.empty()) ++ { ++ ++retryTicksCounter; ++ if (retryTicksCounter >= retryTicksThreshold) ++ { ++ retryTicksCounter = 0; ++ auto it = failedMetricReports.begin(); ++ std::string pathToRetry = *it; ++ failedMetricReports.erase(it); ++ ++ std::cerr << "Workflow: Background retry for " << pathToRetry ++ << "\n"; ++ queryMetricReport(pathToRetry); ++ return; // Network is now busy with the retry ++ } ++ } ++ + ++ticksReading; + timeReading = timeAction; + +@@ -510,6 +528,12 @@ void RedfishServer::advanceDiscovery() + // Collect all metric reports, for use during preflight + for (const std::string& reportPath : reportPaths) + { ++ if (failedMetricReports.find(reportPath) != ++ failedMetricReports.end()) ++ { ++ continue; // Skip failed reports in the current pass ++ } ++ + auto iter = pathsToMetricReports.find(reportPath); + if (iter == pathsToMetricReports.end()) + { +@@ -655,13 +679,6 @@ void RedfishServer::acceptSensors() + std::cerr << "Ready to finalize what was discovered\n"; + } + +- // FUTURE: Make sure this works after accepting sensorsChanged +- for (auto& sensorPair : pathsToSensors) +- { +- sensorPair.second.reset(); +- } +- pathsToSensors.clear(); +- + size_t countDiscovered = 0; + size_t countAlready = 0; + size_t countNotRelevant = 0; +diff --git a/src/RedfishSensor.hpp b/src/RedfishSensor.hpp +index 7a6c996..3a32959 100644 +--- a/src/RedfishSensor.hpp ++++ b/src/RedfishSensor.hpp +@@ -5,6 +5,7 @@ + + #include <boost/asio/steady_timer.hpp> + #include <boost/container/flat_map.hpp> ++#include <boost/container/flat_set.hpp> + #include <nlohmann/json.hpp> + #include <sdbusplus/asio/connection.hpp> + #include <sdbusplus/asio/object_server.hpp> +@@ -258,6 +259,12 @@ class RedfishServer : public std::enable_shared_from_this<RedfishServer> + std::shared_ptr<RedfishMetricReport>> + pathsToMetricReports; + ++ boost::container::flat_set<std::string> failedMetricReports; ++ size_t retryTicksCounter = 0; ++ boost::container::flat_map<std::string, int> quickRetryCounters; ++ static constexpr int maxQuickRetries = 3; ++ static constexpr size_t retryTicksThreshold = RETRY_TICKS_THRESHOLD; ++ + // For remembering starting times to measure how long it took + std::chrono::steady_clock::time_point timeDiscovery; + std::chrono::steady_clock::time_point timeReading; +diff --git a/src/RedfishSensorQuery.cpp b/src/RedfishSensorQuery.cpp +index fb70afe..d3f14d8 100644 +--- a/src/RedfishSensorQuery.cpp ++++ b/src/RedfishSensorQuery.cpp +@@ -819,9 +819,65 @@ void RedfishServer::queryMetricReport(const std::string& path) + } + if (lockThis->doneTransaction(completion)) + { ++ // Clear counter on success ++ lockThis->quickRetryCounters.erase(completion.queryRequest); ++ + if (lockThis->fillFromMetricReport(completion.jsonResponse)) + { +- lockThis->advanceDiscovery(); ++ if (lockThis->discoveryDone) ++ { ++ std::cerr << "Workflow: Background retry success for " ++ << completion.queryRequest ++ << ", updating D-Bus sensors.\n"; ++ lockThis->acceptSensors(); ++ } ++ else ++ { ++ lockThis->advanceDiscovery(); ++ } ++ } ++ } ++ else ++ { ++ if (lockThis->discoveryDone) ++ { ++ // Background retry failed - return directly to the slow queue ++ std::cerr << "Workflow: Background retry failed for " ++ << completion.queryRequest ++ << ", will retry again in next background cycle.\n"; ++ ++ lockThis->failedMetricReports.insert(completion.queryRequest); ++ } ++ else ++ { ++ // Initial discovery failed - use the Quick Retry mechanism ++ int retries = ++ ++(lockThis->quickRetryCounters[completion.queryRequest]); ++ ++ if (retries <= maxQuickRetries) ++ { ++ std::cerr << "Discovery: Metric report query failed for " ++ << completion.queryRequest ++ << ", retry on next tick (" << retries << "/" ++ << maxQuickRetries << ")\n"; ++ // Do nothing. The next timer tick will naturally retry this ++ // URL ++ } ++ else ++ { ++ std::cerr << "Discovery: Metric report query failed for " ++ << completion.queryRequest << " after " ++ << maxQuickRetries ++ << " attempts. Moving to background retry.\n"; ++ ++ lockThis->quickRetryCounters.erase(completion.queryRequest); ++ lockThis->failedMetricReports.insert( ++ completion.queryRequest); ++ ++ // Allow discovery to continue immediately for remaining ++ // resources ++ lockThis->advanceDiscovery(); ++ } + } + } + }; +diff --git a/src/meson.build b/src/meson.build +index a1d9d7a..48b01d2 100644 +--- a/src/meson.build ++++ b/src/meson.build +@@ -259,6 +259,7 @@ if get_option('redfish').enabled() + 'RedfishSensorMain.cpp', + 'RedfishSensorQuery.cpp', + 'RedfishSensorResponse.cpp', ++ cpp_args: ['-DRETRY_TICKS_THRESHOLD=@0@'.format(get_option('redfish-retry-ticks-threshold'))], + dependencies: [ + default_deps, + thresholds_dep, +-- +2.55.0.rc2.803.g1fd1e6609c-goog +
diff --git a/recipes-phosphor/sensors/dbus-sensors_%.bbappend b/recipes-phosphor/sensors/dbus-sensors_%.bbappend index f4d8985..0924780 100644 --- a/recipes-phosphor/sensors/dbus-sensors_%.bbappend +++ b/recipes-phosphor/sensors/dbus-sensors_%.bbappend
@@ -14,6 +14,7 @@ file://0103-RedfishSensor-Intentionally-drop-reported-stale.patch \ file://0104-RedfishSensor-Port-feature-and-other-cleanups.patch \ file://0105-RedfishSensor-Configurable-polling-intervall.patch \ + file://0106-RedfishSensor-Implement-non-blocking-discovery-and-b.patch \ file://0010-dbus-sensors-Creating-association-between-inventory-.patch \ file://0001-intrusionsensor-Add-Assosication-interfaces-for-cabl.patch \ file://0001-adcsensor-Add-optional-battery-status-interface.patch \