SteNicholas commented on code in PR #3781:
URL: https://github.com/apache/celeborn/pull/3781#discussion_r3803523385


##########
master/src/main/java/org/apache/celeborn/service/deploy/master/slotsalloc/LoadAwareSlotsAssignStrategyProvider.java:
##########
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.celeborn.service.deploy.master.slotsalloc;
+
+import org.apache.celeborn.common.CelebornConf;
+import org.apache.celeborn.common.protocol.BuiltInSlotsAssignPolicy;
+
+public final class LoadAwareSlotsAssignStrategyProvider implements 
SlotsAssignStrategyProvider {
+
+  @Override
+  public String getName() {
+    return BuiltInSlotsAssignPolicy.LOADAWARE.name();
+  }
+
+  @Override
+  public SlotsAssignStrategy create(CelebornConf conf) {
+    return new LoadAwareSlotsAssignStrategy(
+        conf.masterSlotAssignLoadAwareDiskGroupNum(),
+        conf.masterSlotAssignLoadAwareDiskGroupGradient(),
+        conf.masterSlotAssignLoadAwareFlushTimeWeight(),
+        conf.masterSlotAssignLoadAwareFetchTimeWeight(),
+        conf.masterSlotAssignLoadAwareActiveSlotsWeight());

Review Comment:
   Please validate these now-dynamic parameters before constructing the 
strategy. For example, `diskGroupNum=0` is accepted, produces no disk groups, 
and silently degrades allocation to the budget-free fallback while the manager 
reports a successful reload. Reject non-positive group counts and non-finite or 
otherwise invalid gradients/weights so the manager keeps the previous valid 
strategy.



##########
master/src/main/java/org/apache/celeborn/service/deploy/master/slotsalloc/SlotsAssignStrategyManager.java:
##########
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.celeborn.service.deploy.master.slotsalloc;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.TreeSet;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.celeborn.common.CelebornConf;
+import org.apache.celeborn.server.common.service.config.ConfigService;
+import org.apache.celeborn.server.common.service.config.SystemConfig;
+
+/**
+ * Discovers slot assignment strategy providers and atomically switches the 
active strategy after
+ * dynamic configuration updates.
+ */
+public final class SlotsAssignStrategyManager {
+
+  private static final Logger LOG = 
LoggerFactory.getLogger(SlotsAssignStrategyManager.class);
+
+  private final CelebornConf staticConf;
+  private final ConfigService configService;
+  private final Map<String, SlotsAssignStrategyProvider> providersByName;
+
+  private volatile ConfiguredStrategy configuredStrategy;
+  private Map<String, String> appliedDynamicConfigs;
+
+  public SlotsAssignStrategyManager(CelebornConf staticConf, ConfigService 
configService) {
+    this.staticConf = staticConf.clone();
+    this.configService = configService;
+    this.providersByName =
+        Collections.unmodifiableMap(
+            
loadProviders(ServiceLoader.load(SlotsAssignStrategyProvider.class)));
+
+    this.appliedDynamicConfigs = currentDynamicConfigs();
+    this.configuredStrategy = createStrategy(appliedDynamicConfigs);
+
+    if (configService != null) {
+      configService.registerListenerOnConfigUpdate(this::reload);
+      // Close the gap between taking the initial snapshot and registering the 
listener.
+      reload();
+    }
+  }
+
+  public SlotsAssignStrategy getStrategy() {
+    return configuredStrategy.strategy;
+  }
+
+  static Map<String, SlotsAssignStrategyProvider> loadProviders(
+      Iterable<SlotsAssignStrategyProvider> providers) {
+    Map<String, SlotsAssignStrategyProvider> providersByName = new 
LinkedHashMap<>();
+    for (SlotsAssignStrategyProvider provider : providers) {
+      String providerName = provider.getName();
+      if (providerName == null || providerName.isEmpty()) {
+        throw new IllegalStateException(
+            "Slots assignment strategy provider "
+                + provider.getClass().getName()
+                + " has an empty name");
+      }
+
+      String normalizedName = providerName.toUpperCase(Locale.ROOT);
+      SlotsAssignStrategyProvider previous = 
providersByName.put(normalizedName, provider);
+      if (previous != null) {
+        throw new IllegalStateException(
+            "Multiple slots assignment strategy providers are registered for '"
+                + providerName
+                + "': "
+                + previous.getClass().getName()
+                + " and "
+                + provider.getClass().getName());
+      }
+    }
+    return providersByName;
+  }
+
+  private synchronized void reload() {
+    Map<String, String> latestDynamicConfigs = currentDynamicConfigs();
+    if (latestDynamicConfigs.equals(appliedDynamicConfigs)) {

Review Comment:
   Comparing only with the last successfully applied snapshot causes an 
unchanged invalid configuration to be retried on every config refresh. 
`BaseConfigServiceImpl` invokes listeners each refresh, and a failed reload 
never updates `appliedDynamicConfigs`, so this repeatedly constructs the 
provider and logs an error until the config changes. Track the last attempted 
snapshot separately, or notify/retry only when the dynamic configuration 
actually changes.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to