From 96e1e643efe3259d9f337345d2964aa18eaf03a5 Mon Sep 17 00:00:00 2001
From: Michael Calmer <michael.calmer@suse.com>
Date: Tue, 8 Apr 2025 15:29:13 +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    | 58 ++++++++++++-------
 1 file changed, 36 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 e864198df06..1ca1629c956 100644
--- a/java/code/src/com/redhat/rhn/manager/ssm/SsmManager.java
+++ b/java/code/src/com/redhat/rhn/manager/ssm/SsmManager.java
@@ -181,7 +181,7 @@ public static List<ScheduleChannelChangesResultDto> scheduleChannelChanges(
                 Stream.empty();
 
         List<ChannelSelectionResult> allResults = Stream.concat(withBaseChannelResults, noBaseChannelResults)
-                                                        .collect(Collectors.toList());
+                .collect(Collectors.toList());
 
         //success channel selections
         Stream<ChannelSelectionResult> succeededResults = allResults.stream().filter(e -> !e.isError());
@@ -236,11 +236,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, new HashMap<>());
         }
         else if (explicitChange(srvChanges)) {
             return handleExplicitBaseChannelChange(earliest, user, Optional.empty(), srv,
-                    srvChanges.stream().findFirst().get());
+                    srvChanges.stream().findFirst().get(), new HashMap<>());
         }
         // no child-only changes possible in case of systems without a base channel
         return null;
@@ -258,23 +258,34 @@ private static Stream<ChannelSelectionResult> handleChannelChangesForSystemsWith
                     .filter(ch -> ch.getOldBaseId().map(currentBase.getId()::equals).orElse(false))
                     .collect(Collectors.toSet());
 
+            Map<String, List<Channel>> accessibleChildsByBase =
+                    oldBaseServers.stream()
+                            .map(Server::getBaseChannel)
+                            .distinct()
+                            .collect(Collectors.toMap(Channel::getLabel,
+                                    bc -> ChannelFactory.getAccessibleChildChannels(bc, user)));
+
             return oldBaseServers.stream()
-                    .map(srv -> handleSingleSystemChannelChange(srvChanges, earliest, user, currentBase, srv));
+                    .map(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));
         }
@@ -285,9 +296,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());
@@ -318,14 +329,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()) {
@@ -335,7 +348,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));
         }
@@ -346,11 +360,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,
@@ -375,8 +386,11 @@ private static Set<ScheduleChannelChangesResultDto> scheduleSubscribeChannelsAct
     }
 
     private static Set<Channel> getChildChannelsForChange(User user, Server server, ChannelChangeDto change,
-                                                           Channel newBaseChannel) {
-        List<Channel> accessibleChildren = ChannelFactory.getAccessibleChildChannels(newBaseChannel, user);
+            Channel newBaseChannel, Map<String, List<Channel>> accessibleChildsByBase) {
+
+        List<Channel> accessibleChildren =
+                accessibleChildsByBase.computeIfAbsent(newBaseChannel.getLabel(),
+                        k -> ChannelFactory.getAccessibleChildChannels(newBaseChannel, user));
         Set<Channel> availableChildChannels = server.getChildChannels();
 
         Set<Channel> result = new HashSet<>();
