This is an automated email from the ASF dual-hosted git repository.

exceptionfactory pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new 0adf611a4b7 NIFI-16155 Apply autoResumeState to scheduling Controller 
Services (#11488)
0adf611a4b7 is described below

commit 0adf611a4b764231cfddac613a6b7928353f256b
Author: Bryan Bende <[email protected]>
AuthorDate: Wed Jul 29 17:12:20 2026 -0400

    NIFI-16155 Apply autoResumeState to scheduling Controller Services (#11488)
    
    Signed-off-by: David Handermann <[email protected]>
---
 .../src/main/asciidoc/administration-guide.adoc    |  2 +-
 .../org/apache/nifi/controller/FlowController.java |  4 ++
 .../serialization/VersionedFlowSynchronizer.java   | 22 +++++--
 .../AutoResumeStateControllerServiceIT.java        | 77 ++++++++++++++++++++++
 4 files changed, 100 insertions(+), 5 deletions(-)

diff --git a/nifi-docs/src/main/asciidoc/administration-guide.adoc 
b/nifi-docs/src/main/asciidoc/administration-guide.adoc
index 2e9e77981b9..138a50631f8 100644
--- a/nifi-docs/src/main/asciidoc/administration-guide.adoc
+++ b/nifi-docs/src/main/asciidoc/administration-guide.adoc
@@ -2889,7 +2889,7 @@ This cleanup mechanism takes into account only 
automatically created archived _f
 |`nifi.flow.configuration.archive.max.time`*|The lifespan of archived 
_flow.json_ files. NiFi will delete expired archive files when it updates 
_flow.json_ if this property is specified. Expiration is determined based on 
current system time and the last modified timestamp of an archived _flow.json_. 
If no archive limitation is specified in _nifi.properties_, NiFi removes 
archives older than `30 days`.
 |`nifi.flow.configuration.archive.max.storage`*|The total data size allowed 
for the archived _flow.json_ files. NiFi will delete the oldest archive files 
until the total archived file size becomes less than this configuration value, 
if this property is specified. If no archive limitation is specified in 
_nifi.properties_, NiFi uses `500 MB` for this.
 |`nifi.flow.configuration.archive.max.count`*|The number of archive files 
allowed. NiFi will delete the oldest archive files so that only N latest 
archives can be kept, if this property is specified.
-|`nifi.flowcontroller.autoResumeState`|Indicates whether -upon restart- the 
components on the NiFi graph should return to their last state. When running in 
cluster, all nodes should have the same value. The default value is `true`.
+|`nifi.flowcontroller.autoResumeState`|Indicates whether -upon restart- the 
components on the NiFi graph, including Processors, Controller Services, and 
other schedulable components, should return to their last state. When running 
in cluster, all nodes should have the same value. The default value is `true`.
 |`nifi.flowcontroller.graceful.shutdown.period`|Indicates the shutdown period. 
The default value is `10 secs`.
 |`nifi.flowcontroller.registry.sync.interval`|Specifies the default recurring 
interval at which NiFi synchronizes the flow configuration with Flow Registry 
Clients. The default value is `30 min`. This value is used for any Flow 
Registry Client that does not configure its own `Synchronization Interval` 
property; a Flow Registry Client that sets that property is synchronized at its 
own interval instead.
 |`nifi.flowservice.writedelay.interval`|When many changes are made to the 
_flow.json_, this property specifies how long to wait before writing out the 
changes, so as to batch the changes into a single write. The default value is 
`500 ms`.
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java
 
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java
index bc899dfd194..4953965ff88 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java
@@ -2496,6 +2496,10 @@ public class FlowController implements 
ReportingTaskProvider, FlowAnalysisRulePr
         return initialized.get();
     }
 
+    public boolean isAutoResumeState() {
+        return nifiProperties.getAutoResumeState();
+    }
+
     public boolean isFlowSynchronized() {
         return flowSynchronized.get();
     }
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/VersionedFlowSynchronizer.java
 
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/VersionedFlowSynchronizer.java
index 11a1de113df..8036b7b7c65 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/VersionedFlowSynchronizer.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/VersionedFlowSynchronizer.java
@@ -108,6 +108,7 @@ import org.apache.nifi.scheduling.SchedulingStrategy;
 import org.apache.nifi.services.FlowService;
 import org.apache.nifi.util.BundleUtils;
 import org.apache.nifi.util.FlowDifferenceFilters;
+import org.apache.nifi.util.NiFiProperties;
 import org.apache.nifi.util.file.FileUtils;
 import org.apache.nifi.web.api.dto.BundleDTO;
 import org.slf4j.Logger;
@@ -1173,11 +1174,15 @@ public class VersionedFlowSynchronizer implements 
FlowSynchronizer {
 
         // Enable any Controller-level services that are intended to be 
enabled.
         if (!toEnable.isEmpty()) {
-            
controller.getControllerServiceProvider().enableControllerServices(toEnable);
+            if (controller.isInitialized() || controller.isAutoResumeState()) {
+                
controller.getControllerServiceProvider().enableControllerServices(toEnable);
 
-            // Validate Controller-level services
-            for (final ControllerServiceNode serviceNode : toEnable) {
-                serviceNode.performValidation();
+                // Validate Controller-level services
+                for (final ControllerServiceNode serviceNode : toEnable) {
+                    serviceNode.performValidation();
+                }
+            } else {
+                logger.info("Leaving {} root Controller Services disabled 
because {} is false", toEnable.size(), NiFiProperties.AUTO_RESUME_STATE);
             }
         }
 
@@ -1587,5 +1592,14 @@ public class VersionedFlowSynchronizer implements 
FlowSynchronizer {
         protected void startNow(final ProcessGroup statelessGroup) {
             flowController.startProcessGroup(statelessGroup);
         }
+
+        @Override
+        protected void enableNow(final Collection<ControllerServiceNode> 
controllerServices) {
+            if (flowController.isInitialized() || 
flowController.isAutoResumeState()) {
+                super.enableNow(controllerServices);
+            } else {
+                logger.info("Leaving {} Controller Services disabled because 
{} is false", controllerServices.size(), NiFiProperties.AUTO_RESUME_STATE);
+            }
+        }
     }
 }
diff --git 
a/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/restart/AutoResumeStateControllerServiceIT.java
 
b/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/restart/AutoResumeStateControllerServiceIT.java
new file mode 100644
index 00000000000..7a4c64a21d6
--- /dev/null
+++ 
b/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/restart/AutoResumeStateControllerServiceIT.java
@@ -0,0 +1,77 @@
+/*
+ * 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.nifi.tests.system.restart;
+
+import org.apache.nifi.tests.system.NiFiSystemIT;
+import org.apache.nifi.toolkit.client.NiFiClientException;
+import org.apache.nifi.util.NiFiProperties;
+import org.apache.nifi.web.api.entity.ControllerServiceEntity;
+import org.apache.nifi.web.api.entity.ProcessGroupEntity;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+class AutoResumeStateControllerServiceIT extends NiFiSystemIT {
+
+    private static final String ENABLED = "ENABLED";
+
+    @Override
+    protected boolean isDestroyEnvironmentAfterEachTest() {
+        return true;
+    }
+
+    @Override
+    protected boolean isAllowFactoryReuse() {
+        return false;
+    }
+
+    @Test
+    void testRootControllerServiceNotResumedWhenAutoResumeDisabled() throws 
NiFiClientException, IOException {
+        final ControllerServiceEntity service = 
getClientUtil().createRootLevelControllerService("StandardCountService");
+        getClientUtil().enableControllerService(service);
+        getClientUtil().waitForControllerServiceRunStatus(service.getId(), 
ENABLED);
+
+        restartWithAutoResumeStateDisabled();
+
+        final ControllerServiceEntity serviceAfterRestart = 
getNifiClient().getControllerServicesClient().getControllerService(service.getId());
+        assertNotEquals(ENABLED, 
serviceAfterRestart.getComponent().getState());
+    }
+
+    @Test
+    void testProcessGroupControllerServiceNotResumedWhenAutoResumeDisabled() 
throws NiFiClientException, IOException {
+        final ProcessGroupEntity processGroup = 
getClientUtil().createProcessGroup("Auto Resume Test", "root");
+        final ControllerServiceEntity service = 
getClientUtil().createControllerService("StandardCountService", 
processGroup.getId());
+        getClientUtil().enableControllerService(service);
+        getClientUtil().waitForControllerServiceRunStatus(service.getId(), 
ENABLED);
+
+        restartWithAutoResumeStateDisabled();
+
+        final ControllerServiceEntity serviceAfterRestart = 
getNifiClient().getControllerServicesClient().getControllerService(service.getId());
+        assertNotEquals(ENABLED, 
serviceAfterRestart.getComponent().getState());
+    }
+
+    private void restartWithAutoResumeStateDisabled() throws IOException {
+        getNiFiInstance().stop();
+        getNiFiInstance().setProperty(NiFiProperties.AUTO_RESUME_STATE, 
"false");
+        getNiFiInstance().start(true);
+
+        setupClient();
+    }
+}

Reply via email to