From 9105bc43fa2bf8b58328a90a5f03387ad488800e Mon Sep 17 00:00:00 2001
From: Michael Calmer <michael.calmer@suse.com>
Date: Wed, 2 Apr 2025 14:32:42 +0200
Subject: [PATCH] provide accessibleChildsByBase access map to
 getChildChannelsForChange

getChildChannelsForChange is called for every server and compute
every time getAccessibleChildChannels for the base channel of the server.
When a lot of server use the same base channel, this access map can
massivly reduce the time because we need to compute the children only
one time for every base channel.
---
 .../redhat/rhn/manager/ssm/SsmManager.java    | 60 ++++++++++++-------
 1 file changed, 38 insertions(+), 22 deletions(-)
#L3PD: bsc#1239154

diff --git a/java/code/src/com/redhat/rhn/manager/ssm/SsmManager.java b/java/code/src/com/redhat/rhn/manager/ssm/SsmManager.java
index 893881d7593..8b27c5cadfc 100644
--- a/java/code/src/com/redhat/rhn/manager/ssm/SsmManager.java
+++ b/java/code/src/com/redhat/rhn/manager/ssm/SsmManager.java
@@ -48,6 +48,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -242,11 +243,11 @@ private static ChannelSelectionResult handleSingleSystemChannelAddition(Set<Chan
         Server srv = ServerFactory.lookupById(srvDto.getId());
 
         if (defaultBaseChange(srvChanges)) {
-            return handleDefaultBaseChannelChange(earliest, user, srv, srvChanges);
+            return handleDefaultBaseChannelChange(earliest, user, srv, srvChanges, Collections.emptyMap());
         }
         else if (explicitChange(srvChanges)) {
             return handleExplicitBaseChannelChange(earliest, user, Optional.empty(), srv,
-                    srvChanges.stream().findFirst().get());
+                    srvChanges.stream().findFirst().get(), Collections.emptyMap());
         }
         // no child-only changes possible in case of systems without a base channel
         return null;
@@ -264,24 +265,36 @@ private static Stream<ChannelSelectionResult> handleChannelChangesForSystemsWith
                     .filter(ch -> ch.getOldBaseId().map(currentBase.getId()::equals).orElse(false))
                     .collect(Collectors.toSet());
 
+            Map<String, List<Channel>> accessibleChildsByBase =
+                    TimeUtils.logTime(LOG, "SsmManager: compute accessibleChildrenByBaseChannel", () ->
+                            oldBaseServers.stream()
+                                    .map(Server::getBaseChannel)
+                                    .distinct()
+                                    .collect(Collectors.toMap(Channel::getLabel,
+                                            bc -> ChannelFactory.getAccessibleChildChannels(bc, user))));
+
             return oldBaseServers.stream()
                     .map(srv -> TimeUtils.logTime(LOG, "SsmManager.handleSingleSystemChannelChange", () ->
-                            handleSingleSystemChannelChange(srvChanges, earliest, user, currentBase, srv)));
+                            handleSingleSystemChannelChange(srvChanges, earliest, user, currentBase, srv,
+                                    accessibleChildsByBase)));
         });
     }
 
-    private static ChannelSelectionResult handleSingleSystemChannelChange(Set<ChannelChangeDto> srvChanges,
-            Date earliest, User user, Channel currentBase, Server srv) {
+    private static ChannelSelectionResult handleSingleSystemChannelChange(
+            Set<ChannelChangeDto> srvChanges, Date earliest, User user, Channel currentBase,
+            Server srv, Map<String, List<Channel>> accessibleChildsByBase) {
+
         if (defaultBaseChange(srvChanges)) {
-            return handleDefaultBaseChannelChange(earliest, user, srv, srvChanges);
+            return handleDefaultBaseChannelChange(earliest, user, srv, srvChanges, accessibleChildsByBase);
         }
         else if (explicitChange(srvChanges)) {
             return handleExplicitBaseChannelChange(earliest, user,  Optional.of(currentBase), srv,
-                    srvChanges.stream().findFirst().get());
+                    srvChanges.stream().findFirst().get(), accessibleChildsByBase);
         }
         else if (onlyChildChannelsChange(srvChanges)) {
             ChannelChangeDto srvChange = srvChanges.stream().findFirst().get();
-            Set<Channel> childChannels = getChildChannelsForChange(user, srv, srvChange, srv.getBaseChannel());
+            Set<Channel> childChannels = getChildChannelsForChange(user, srv, srvChange, srv.getBaseChannel(),
+                    accessibleChildsByBase);
 
             return new ChannelSelectionResult(srv, new ChannelSelection(Optional.empty(), childChannels));
         }
@@ -292,9 +305,9 @@ else if (onlyChildChannelsChange(srvChanges)) {
     }
 
     private static ChannelSelectionResult handleExplicitBaseChannelChange(Date earliest, User user,
-                                                        Optional<Channel> currentBase,
-                                                        Server srv,
-                                                        ChannelChangeDto srvChange) {
+            Optional<Channel> currentBase, Server srv,
+            ChannelChangeDto srvChange, Map<String, List<Channel>> accessibleChildsByBase) {
+
         boolean baseChange =
                 (currentBase.isPresent() && !currentBase.get().getId().equals(srvChange.getNewBaseId().orElse(null))) ||
                 !(currentBase.isPresent() && srvChange.getNewBaseId().isPresent());
@@ -325,14 +338,16 @@ private static ChannelSelectionResult handleExplicitBaseChannelChange(Date earli
         }
         else {
             Channel newBaseChannel = ChannelFactory.lookupById(srvChange.getNewBaseId().get());
-            Set<Channel> childChannels = getChildChannelsForChange(user, srv, srvChange, newBaseChannel);
+            Set<Channel> childChannels = getChildChannelsForChange(user, srv, srvChange, newBaseChannel,
+                    accessibleChildsByBase);
 
             return new ChannelSelectionResult(srv, new ChannelSelection(Optional.of(newBaseChannel), childChannels));
         }
     }
 
     private static ChannelSelectionResult handleDefaultBaseChannelChange(Date earliest, User user,
-                                                       Server srv, Set<ChannelChangeDto> srvChanges) {
+            Server srv, Set<ChannelChangeDto> srvChanges, Map<String, List<Channel>> accessibleChildsByBase) {
+
         Optional<Channel> guessedChannel =
                 ChannelManager.guessServerBaseChannel(user, srv.getId());
         if (!guessedChannel.isPresent()) {
@@ -342,7 +357,8 @@ private static ChannelSelectionResult handleDefaultBaseChannelChange(Date earlie
         Optional<ChannelChangeDto> srvChange = getChangeByDefaultBase(srvChanges, guessedChannel.get());
         if (srvChange.isPresent()) {
             Channel newBaseChannel = ChannelFactory.lookupById(srvChange.get().getNewBaseId().get());
-            Set<Channel> childChannels = getChildChannelsForChange(user, srv, srvChange.get(), newBaseChannel);
+            Set<Channel> childChannels = getChildChannelsForChange(user, srv, srvChange.get(), newBaseChannel,
+                    accessibleChildsByBase);
 
             return new ChannelSelectionResult(srv, new ChannelSelection(Optional.of(newBaseChannel), childChannels));
         }
@@ -353,11 +369,8 @@ private static ChannelSelectionResult handleDefaultBaseChannelChange(Date earlie
     }
 
     private static Set<ScheduleChannelChangesResultDto> scheduleSubscribeChannelsAction(
-                                                                                   List<ChannelSelectionResult> results,
-                                                                                   Optional<Channel> baseChannel,
-                                                                                   Set<Channel> childChannels,
-                                                                                   User user, Date earliest,
-                                                                                   ActionChain actionChain) {
+            List<ChannelSelectionResult> results, Optional<Channel> baseChannel, Set<Channel> childChannels,
+            User user, Date earliest, ActionChain actionChain) {
         try {
             Set<Action> actions = ActionChainManager.scheduleSubscribeChannelsAction(
                     user,
@@ -381,11 +394,14 @@ private static Set<ScheduleChannelChangesResultDto> scheduleSubscribeChannelsAct
         }
     }
 
-    private static Set<Channel> getChildChannelsForChange(User user, Server server, ChannelChangeDto change,
-                                                           Channel newBaseChannel) {
+    private static Set<Channel> getChildChannelsForChange(
+            User user, Server server, ChannelChangeDto change,
+            Channel newBaseChannel, Map<String, List<Channel>> accessibleChildsByBase) {
+
         List<Channel> accessibleChildren =
                 TimeUtils.logTime(LOG, "SsmManager.getChildChannelsForChange accessibleChildren", () ->
-                        ChannelFactory.getAccessibleChildChannels(newBaseChannel, user));
+                        accessibleChildsByBase.getOrDefault(newBaseChannel.getLabel(),
+                                ChannelFactory.getAccessibleChildChannels(newBaseChannel, user)));
         Set<Channel> availableChildChannels =
                 TimeUtils.logTime(LOG, "SsmManager.getChildChannelsForChange availableChildChannels",
                         server::getChildChannels);
