From bd7def1768e360cc491d56805f7c16784c2f4fbe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Pecka?= <tomas.pecka@cesnet.cz>
Date: Wed, 15 Jan 2025 18:27:25 +0100
Subject: [PATCH 24/44] restconf: make fetching replay info reusable
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Organization: Wires

We are querying sysrepo for replay support in our modules for NETCONF
stream. This part of code will be reused for dynamic subscriptions to
NETCONF stream as well, so let's make it reusable.

Change-Id: Id5bc656619acb8e56dfafde23b03107139d34e94
Signed-off-by: Mattias Walström <lazzer@gmail.com>
---
 src/restconf/NotificationStream.cpp | 57 +++++++++++++++++------------
 1 file changed, 34 insertions(+), 23 deletions(-)

diff --git a/src/restconf/NotificationStream.cpp b/src/restconf/NotificationStream.cpp
index eeddc04..e00c39d 100644
--- a/src/restconf/NotificationStream.cpp
+++ b/src/restconf/NotificationStream.cpp
@@ -50,6 +50,36 @@ bool canBeSubscribed(const libyang::Module& mod)
 {
     return mod.implemented() && mod.name() != "sysrepo";
 }
+
+struct SysrepoReplayInfo {
+    bool enabled;
+    std::optional<sysrepo::NotificationTimeStamp> earliestNotification;
+};
+
+SysrepoReplayInfo sysrepoReplayInfo(sysrepo::Session& session)
+{
+    decltype(sysrepo::ModuleReplaySupport::earliestNotification) globalEarliestNotification;
+    bool replayEnabled = false;
+
+    for (const auto& mod : session.getContext().modules()) {
+        if (!canBeSubscribed(mod)) {
+            continue;
+        }
+
+        auto replay = session.getConnection().getModuleReplaySupport(mod.name());
+        replayEnabled |= replay.enabled;
+
+        if (replay.earliestNotification) {
+            if (!globalEarliestNotification) {
+                globalEarliestNotification = replay.earliestNotification;
+            } else {
+                globalEarliestNotification = std::min(*replay.earliestNotification, *globalEarliestNotification);
+            }
+        }
+    }
+
+    return {replayEnabled, globalEarliestNotification};
+}
 }
 
 namespace rousette::restconf {
@@ -114,28 +144,9 @@ void NotificationStream::activate()
 /** @brief Creates and fills ietf-restconf-monitoring:restconf-state/stream. To be called in oper callback. */
 void notificationStreamList(sysrepo::Session& session, std::optional<libyang::DataNode>& parent, const std::string& streamsPrefix)
 {
+    const auto replayInfo = sysrepoReplayInfo(session);
     static const auto prefix = "/ietf-restconf-monitoring:restconf-state/streams/stream[name='NETCONF']"s;
 
-    decltype(sysrepo::ModuleReplaySupport::earliestNotification) globalEarliestNotification;
-    bool replayEnabled = false;
-
-    for (const auto& mod : session.getContext().modules()) {
-        if (!canBeSubscribed(mod)) {
-            continue;
-        }
-
-        auto replay = session.getConnection().getModuleReplaySupport(mod.name());
-        replayEnabled |= replay.enabled;
-
-        if (replay.earliestNotification) {
-            if (!globalEarliestNotification) {
-                globalEarliestNotification = replay.earliestNotification;
-            } else {
-                globalEarliestNotification = std::min(*replay.earliestNotification, *globalEarliestNotification);
-            }
-        }
-    }
-
     if (!parent) {
         parent = session.getContext().newPath(prefix + "/description", "Default NETCONF notification stream");
     } else {
@@ -144,11 +155,11 @@ void notificationStreamList(sysrepo::Session& session, std::optional<libyang::Da
     parent->newPath(prefix + "/access[encoding='xml']/location", streamsPrefix + "NETCONF/XML");
     parent->newPath(prefix + "/access[encoding='json']/location", streamsPrefix + "NETCONF/JSON");
 
-    if (replayEnabled) {
+    if (replayInfo.enabled) {
         parent->newPath(prefix + "/replay-support", "true");
 
-        if (globalEarliestNotification) {
-            parent->newPath(prefix + "/replay-log-creation-time", libyang::yangTimeFormat(*globalEarliestNotification, libyang::TimezoneInterpretation::Local));
+        if (replayInfo.earliestNotification) {
+            parent->newPath(prefix + "/replay-log-creation-time", libyang::yangTimeFormat(*replayInfo.earliestNotification, libyang::TimezoneInterpretation::Local));
         }
     }
 }
-- 
2.43.0

