2323import java .io .File ;
2424import java .io .IOException ;
2525import java .util .*;
26- import java .util .concurrent .Future ;
27- import java .util .concurrent .TimeUnit ;
2826
2927/**
3028 * Default implementation of ModulesLoader. Loads everything except assets via the REST API. Assets are either loaded
@@ -43,7 +41,7 @@ public class DefaultModulesLoader extends LoggingObject implements ModulesLoader
4341 // For parallelizing writes of modules
4442 private TaskExecutor taskExecutor ;
4543 private int taskThreadCount = 16 ;
46- private List < Future > taskFutures ;
44+ private boolean shutdownTaskExecutorAfterLoadingModules = true ;
4745
4846 /**
4947 * When set to true, exceptions thrown while loading transforms and resources will be caught and logged, and the
@@ -119,7 +117,6 @@ public Set<File> loadModules(File baseDir, ModulesFinder modulesFinder, Database
119117 if (taskExecutor == null ) {
120118 initializeDefaultTaskExecutor ();
121119 }
122- taskFutures = new ArrayList <>();
123120
124121 Set <File > loadedModules = new HashSet <>();
125122 loadProperties (modules , loadedModules );
@@ -130,8 +127,7 @@ public Set<File> loadModules(File baseDir, ModulesFinder modulesFinder, Database
130127 loadTransforms (modules , loadedModules );
131128 loadResources (modules , loadedModules );
132129
133- // Wait for thread pool to complete
134- waitForTaskFuturesToComplete ();
130+ waitForTaskExecutorToFinish ();
135131
136132 if (logger .isDebugEnabled ()) {
137133 logger .debug ("Finished loading modules from base directory: " + baseDir .getAbsolutePath ());
@@ -143,33 +139,20 @@ public Set<File> loadModules(File baseDir, ModulesFinder modulesFinder, Database
143139 * If an AsyncTaskExecutor is used for loading options/services/transforms, we need to wait for the tasks to complete
144140 * before we e.g. release the DatabaseClient.
145141 */
146- protected void waitForTaskFuturesToComplete () {
147- int size = taskFutures .size ();
148- for (int i = 0 ; i < size ; i ++) {
149- Future <?> f = taskFutures .get (i );
150- if (f .isDone () || f .isCancelled ()) {
151- continue ;
152- }
153- try {
154- // Wait up to 1 hour for a write to ML to finish (should never happen)
155- f .get (1 , TimeUnit .HOURS );
156- } catch (Exception ex ) {
157- logger .warn ("Unable to wait for last task future to finish: " + ex .getMessage (), ex );
158- }
159- }
160-
161- if (taskExecutor instanceof ExecutorConfigurationSupport ) {
162- ((ExecutorConfigurationSupport )taskExecutor ).shutdown ();
163- } else if (taskExecutor instanceof DisposableBean ) {
164- try {
165- ((DisposableBean ) taskExecutor ).destroy ();
166- } catch (Exception ex ) {
167- logger .warn ("Unexpected exception while calling destroy() on taskExecutor: " + ex .getMessage (), ex );
168- }
169- }
170-
171- // Null this out so a new thread pool is created if loadModules is called again on this object
172- this .taskExecutor = null ;
142+ protected void waitForTaskExecutorToFinish () {
143+ if (shutdownTaskExecutorAfterLoadingModules ) {
144+ if (taskExecutor instanceof ExecutorConfigurationSupport ) {
145+ ((ExecutorConfigurationSupport ) taskExecutor ).shutdown ();
146+ } else if (taskExecutor instanceof DisposableBean ) {
147+ try {
148+ ((DisposableBean ) taskExecutor ).destroy ();
149+ } catch (Exception ex ) {
150+ logger .warn ("Unexpected exception while calling destroy() on taskExecutor: " + ex .getMessage (), ex );
151+ }
152+ }
153+ } else if (logger .isDebugEnabled ()) {
154+ logger .debug ("shutdownTaskExecutorAfterLoadingModules is set to false, so not shutting down taskExecutor" );
155+ }
173156 }
174157
175158 /**
@@ -643,4 +626,8 @@ public void setTaskExecutor(TaskExecutor taskExecutor) {
643626 public void setTaskThreadCount (int taskThreadCount ) {
644627 this .taskThreadCount = taskThreadCount ;
645628 }
629+
630+ public void setShutdownTaskExecutorAfterLoadingModules (boolean shutdownTaskExecutorAfterLoadingModules ) {
631+ this .shutdownTaskExecutorAfterLoadingModules = shutdownTaskExecutorAfterLoadingModules ;
632+ }
646633}
0 commit comments