exceptionfactory commented on code in PR #10619:
URL: https://github.com/apache/nifi/pull/10619#discussion_r2604404125


##########
nifi-framework-bundle/nifi-framework-extensions/nifi-framework-kubernetes-bundle/nifi-framework-kubernetes-state-provider/src/main/java/org/apache/nifi/kubernetes/state/provider/KubernetesConfigMapStateProvider.java:
##########
@@ -154,64 +154,28 @@ public void shutdown() {
     @Override
     public void setState(final Map<String, String> state, final String 
componentId) throws IOException {
         try {
-            final ConfigMap configMap = createConfigMapBuilder(state, 
componentId).build();
-            Resource<ConfigMap> configMapResource = 
kubernetesClient.configMaps().resource(configMap);
-            final String configMapName = configMap.getMetadata().getName();
-
-            ConfigMap configMapCreated = null;
+            final ConfigMap configMap = createConfigMapBuilder(state, 
componentId, Optional.empty()).build();
+            ConfigMap configMapResult = null;
 
-            // Attempt to create or update, up to 3 times. We expect that we 
will update more frequently than create
-            // so we first attempt to update. If we get back a 404, then we 
create it.
-            boolean create = false;
+            // Attempt to create or update, up to 3 times
             for (int attempt = 0; attempt < MAX_UPDATE_ATTEMPTS; attempt++) {
                 try {
-                    if (create) {
-                        configMapCreated = configMapResource.create();
+                    final ConfigMap existingConfigMap = 
kubernetesClient.configMaps().resource(configMap).get();
+                    if (existingConfigMap == null) {
+                        configMapResult = 
kubernetesClient.configMaps().resource(configMap).create();
                     } else {
-                        configMapCreated = configMapResource.update();
+                        existingConfigMap.setData(configMap.getData());
+                        configMapResult = 
kubernetesClient.configMaps().resource(existingConfigMap).update();
                     }
-
                     break;
                 } catch (final KubernetesClientException e) {
                     final int returnCode = e.getCode();
-                    if (returnCode == HttpURLConnection.HTTP_NOT_FOUND) {
-                        // A 404 return code indicates that we need to create 
the resource instead of update it.
-                        // Now, we will attempt to create the resource instead 
of update it, so we'll reset the attempt counter.
-                        attempt = 0;
-                        create = true;
-                        continue;
-                    }
-
-                    if (returnCode == HttpURLConnection.HTTP_CONFLICT) {
-                        logger.debug("Update conflict detected when setting 
state for Component ID [{}]. Attempt {} of {}.", componentId, attempt + 1, 
MAX_UPDATE_ATTEMPTS);
-
-                        if (attempt < MAX_UPDATE_ATTEMPTS - 1) {
-                            final ConfigMap latestConfigMap = 
kubernetesClient.configMaps()
-                                    .inNamespace(namespace)
-                                    .withName(configMapName)
-                                    .get();
-
-                            if (latestConfigMap != null) {
-                                final ObjectMeta latestMetadata = 
latestConfigMap.getMetadata();
-                                final String latestResourceVersion = 
latestMetadata != null ? latestMetadata.getResourceVersion() : null;
-
-                                if (latestResourceVersion != null) {
-                                    
configMap.getMetadata().setResourceVersion(latestResourceVersion);
-                                    configMapResource = 
kubernetesClient.configMaps().resource(configMap);
-                                    logger.debug("Retrying state update for 
Component ID [{}] with resource version [{}]", componentId, 
latestResourceVersion);
-                                    continue;
-                                }
-                            }
-                        }
-
-                        throw e;
-                    }
-
-                    if (returnCode >= 500) {
-                        // Server-side error. We should retry, up to some 
number of attempts.
+                    if (returnCode == HttpURLConnection.HTTP_CONFLICT || 
returnCode >= 500) {
+                        // Conflict or Server-side error. We should retry, up 
to some number of attempts.
                         if (attempt == MAX_UPDATE_ATTEMPTS - 1) {
                             throw e;
                         }
+                        logger.warn("Failed to update state for Component ID 
[{}]. Attempt {} of {}.", componentId, attempt + 1, MAX_UPDATE_ATTEMPTS, e);

Review Comment:
   Should this be a warning? It if it uncommon, that a warning seems useful. If 
it is common, an `INFO` message seems better.
   
   ```suggestion
                           logger.warn("Failed to update state for Component ID 
[{}] on attempt {} of {}", componentId, attempt + 1, MAX_UPDATE_ATTEMPTS, e);
   ```



##########
nifi-framework-bundle/nifi-framework-extensions/nifi-framework-kubernetes-bundle/nifi-framework-kubernetes-state-provider/src/main/java/org/apache/nifi/kubernetes/state/provider/KubernetesConfigMapStateProvider.java:
##########
@@ -154,64 +154,28 @@ public void shutdown() {
     @Override
     public void setState(final Map<String, String> state, final String 
componentId) throws IOException {
         try {
-            final ConfigMap configMap = createConfigMapBuilder(state, 
componentId).build();
-            Resource<ConfigMap> configMapResource = 
kubernetesClient.configMaps().resource(configMap);
-            final String configMapName = configMap.getMetadata().getName();
-
-            ConfigMap configMapCreated = null;
+            final ConfigMap configMap = createConfigMapBuilder(state, 
componentId, Optional.empty()).build();
+            ConfigMap configMapResult = null;
 
-            // Attempt to create or update, up to 3 times. We expect that we 
will update more frequently than create
-            // so we first attempt to update. If we get back a 404, then we 
create it.
-            boolean create = false;
+            // Attempt to create or update, up to 3 times
             for (int attempt = 0; attempt < MAX_UPDATE_ATTEMPTS; attempt++) {
                 try {
-                    if (create) {
-                        configMapCreated = configMapResource.create();
+                    final ConfigMap existingConfigMap = 
kubernetesClient.configMaps().resource(configMap).get();
+                    if (existingConfigMap == null) {
+                        configMapResult = 
kubernetesClient.configMaps().resource(configMap).create();
                     } else {
-                        configMapCreated = configMapResource.update();
+                        existingConfigMap.setData(configMap.getData());
+                        configMapResult = 
kubernetesClient.configMaps().resource(existingConfigMap).update();
                     }
-
                     break;
                 } catch (final KubernetesClientException e) {
                     final int returnCode = e.getCode();
-                    if (returnCode == HttpURLConnection.HTTP_NOT_FOUND) {
-                        // A 404 return code indicates that we need to create 
the resource instead of update it.
-                        // Now, we will attempt to create the resource instead 
of update it, so we'll reset the attempt counter.
-                        attempt = 0;
-                        create = true;
-                        continue;
-                    }
-
-                    if (returnCode == HttpURLConnection.HTTP_CONFLICT) {
-                        logger.debug("Update conflict detected when setting 
state for Component ID [{}]. Attempt {} of {}.", componentId, attempt + 1, 
MAX_UPDATE_ATTEMPTS);
-
-                        if (attempt < MAX_UPDATE_ATTEMPTS - 1) {
-                            final ConfigMap latestConfigMap = 
kubernetesClient.configMaps()
-                                    .inNamespace(namespace)
-                                    .withName(configMapName)
-                                    .get();
-
-                            if (latestConfigMap != null) {
-                                final ObjectMeta latestMetadata = 
latestConfigMap.getMetadata();
-                                final String latestResourceVersion = 
latestMetadata != null ? latestMetadata.getResourceVersion() : null;
-
-                                if (latestResourceVersion != null) {
-                                    
configMap.getMetadata().setResourceVersion(latestResourceVersion);
-                                    configMapResource = 
kubernetesClient.configMaps().resource(configMap);
-                                    logger.debug("Retrying state update for 
Component ID [{}] with resource version [{}]", componentId, 
latestResourceVersion);
-                                    continue;
-                                }
-                            }
-                        }
-
-                        throw e;
-                    }
-
-                    if (returnCode >= 500) {
-                        // Server-side error. We should retry, up to some 
number of attempts.
+                    if (returnCode == HttpURLConnection.HTTP_CONFLICT || 
returnCode >= 500) {

Review Comment:
   Recommend replacing `500` with `HttpURLConnection.HTTP_INTERNAL_ERROR` to 
align with the use of `HTTP_CONFLICT`.



##########
nifi-framework-bundle/nifi-framework-extensions/nifi-framework-kubernetes-bundle/nifi-framework-kubernetes-state-provider/src/main/java/org/apache/nifi/kubernetes/state/provider/KubernetesConfigMapStateProvider.java:
##########
@@ -411,15 +381,28 @@ private Resource<ConfigMap> configMapResource(final 
String componentId) {
         return 
kubernetesClient.configMaps().inNamespace(namespace).withName(name);
     }
 
-    private ConfigMapBuilder createConfigMapBuilder(final Map<String, String> 
state, final String componentId) {
-        final Map<String, String> encodedData = getEncodedMap(state);
+    private ConfigMapBuilder createConfigMapBuilder(final Map<String, String> 
state, final String componentId, final Optional<ObjectMeta> existingMetadata) {
         final String name = getConfigMapName(componentId);
-        return new ConfigMapBuilder()
+
+        final ConfigMapBuilder configMapBuilder;
+        if (existingMetadata.isPresent()) {
+            if (!namespace.equals(existingMetadata.get().getNamespace())) {
+                throw new IllegalArgumentException("Expected existing 
ConfigMap namespace [%s], but was [%s]".formatted(namespace, 
existingMetadata.get().getNamespace()));
+            }
+            if (!name.equals(existingMetadata.get().getName())) {
+                throw new IllegalArgumentException("Expected existing 
ConfigMap name [%s], but was [%s]".formatted(name, 
existingMetadata.get().getName()));
+            }

Review Comment:
   Is very likely to happen given that this is framework-level component? 
Perhaps rewriting this a bit to declare the `ObjectMeta` instance on one line, 
and then checking the positive conditions of `namespace` and `name` matching.



##########
nifi-framework-bundle/nifi-framework-extensions/nifi-framework-kubernetes-bundle/nifi-framework-kubernetes-state-provider/src/main/java/org/apache/nifi/kubernetes/state/provider/KubernetesConfigMapStateProvider.java:
##########
@@ -411,15 +381,28 @@ private Resource<ConfigMap> configMapResource(final 
String componentId) {
         return 
kubernetesClient.configMaps().inNamespace(namespace).withName(name);
     }
 
-    private ConfigMapBuilder createConfigMapBuilder(final Map<String, String> 
state, final String componentId) {
-        final Map<String, String> encodedData = getEncodedMap(state);
+    private ConfigMapBuilder createConfigMapBuilder(final Map<String, String> 
state, final String componentId, final Optional<ObjectMeta> existingMetadata) {

Review Comment:
   Instead of passing the `Optional` to this `private` method, it looks like 
the `ObjectMeta` itself could be passed and checked for `null`.



##########
nifi-framework-bundle/nifi-framework-extensions/nifi-framework-kubernetes-bundle/nifi-framework-kubernetes-state-provider/src/main/java/org/apache/nifi/kubernetes/state/provider/KubernetesConfigMapStateProvider.java:
##########
@@ -272,7 +237,12 @@ public StateMap getState(final String componentId) throws 
IOException {
      */
     @Override
     public boolean replace(final StateMap currentState, final Map<String, 
String> state, final String componentId) throws IOException {
-        final ConfigMapBuilder configMapBuilder = 
createConfigMapBuilder(state, componentId);
+        if (!(currentState instanceof StandardStateMap)) {
+            throw new IllegalStateException("Current state is not an instance 
of StandardStateMap");
+        }
+
+        final Optional<ObjectMeta> existingMetadata = ((StandardStateMap) 
currentState).getConfigMapMetadata();

Review Comment:
   The casting is a bit verbose as written. Instead, what do you think about 
using pattern variables as `if (currentState instanceof StandardStateMap 
standardStateMap) { ... } else { throw new IllegalStateException() }`



-- 
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