1616 */
1717package org .apache .camel .component .file .cluster ;
1818
19+ import java .util .concurrent .ExecutorService ;
1920import java .util .concurrent .ScheduledExecutorService ;
2021import java .util .concurrent .TimeUnit ;
2122import java .util .concurrent .locks .Lock ;
@@ -32,13 +33,20 @@ public class FileLockClusterService extends AbstractCamelClusterService<FileLock
3233 private TimeUnit acquireLockIntervalUnit ;
3334 private ScheduledExecutorService executor ;
3435 private int heartbeatTimeoutMultiplier ;
36+ private int clusterDataTaskMaxAttempts ;
37+ private long clusterDataTaskTimeout ;
38+ private TimeUnit clusterDataTaskTimeoutUnit ;
39+ private ExecutorService clusterDataTaskExecutor ;
3540
3641 public FileLockClusterService () {
3742 this .acquireLockDelay = 1 ;
3843 this .acquireLockDelayUnit = TimeUnit .SECONDS ;
3944 this .acquireLockInterval = 10 ;
4045 this .acquireLockIntervalUnit = TimeUnit .SECONDS ;
4146 this .heartbeatTimeoutMultiplier = 5 ;
47+ this .clusterDataTaskMaxAttempts = 5 ;
48+ this .clusterDataTaskTimeout = 10 ;
49+ this .clusterDataTaskTimeoutUnit = TimeUnit .SECONDS ;
4250 }
4351
4452 @ Override
@@ -120,13 +128,74 @@ public void setAcquireLockIntervalUnit(TimeUnit acquireLockIntervalUnit) {
120128 * <p>
121129 */
122130 public void setHeartbeatTimeoutMultiplier (int heartbeatTimeoutMultiplier ) {
131+ if (heartbeatTimeoutMultiplier <= 0 ) {
132+ throw new IllegalArgumentException ("HeartbeatTimeoutMultiplier must be greater than 0" );
133+ }
123134 this .heartbeatTimeoutMultiplier = heartbeatTimeoutMultiplier ;
124135 }
125136
126137 public int getHeartbeatTimeoutMultiplier () {
127138 return heartbeatTimeoutMultiplier ;
128139 }
129140
141+ /**
142+ * Sets how many times a cluster data task will run, counting both the first execution and subsequent retries in
143+ * case of failure or timeout. The default is 5 attempts.
144+ * <p>
145+ * This can be useful when the cluster data root is on network based file storage, where I/O operations may
146+ * occasionally block for long or unpredictable periods.
147+ */
148+ public void setClusterDataTaskMaxAttempts (int clusterDataTaskMaxAttempts ) {
149+ if (clusterDataTaskMaxAttempts <= 0 ) {
150+ throw new IllegalArgumentException ("clusterDataTaskMaxRetries must be greater than 0" );
151+ }
152+ this .clusterDataTaskMaxAttempts = clusterDataTaskMaxAttempts ;
153+ }
154+
155+ public int getClusterDataTaskMaxAttempts () {
156+ return clusterDataTaskMaxAttempts ;
157+ }
158+
159+ /**
160+ * Sets the timeout for a cluster data task (reading or writing cluster data). The default is 10 seconds.
161+ * <p>
162+ * Timeouts are useful when the cluster data root is on network storage, where I/O operations may occasionally block
163+ * for long or unpredictable periods.
164+ */
165+ public void setClusterDataTaskTimeout (long clusterDataTaskTimeout ) {
166+ if (clusterDataTaskTimeout <= 0 ) {
167+ throw new IllegalArgumentException ("clusterDataTaskMaxRetries must be greater than 0" );
168+ }
169+ this .clusterDataTaskTimeout = clusterDataTaskTimeout ;
170+ }
171+
172+ public long getClusterDataTaskTimeout () {
173+ return clusterDataTaskTimeout ;
174+ }
175+
176+ /**
177+ * The time unit for the clusterDataTaskTimeoutUnit, default to TimeUnit.SECONDS.
178+ */
179+ public void setClusterDataTaskTimeoutUnit (TimeUnit clusterDataTaskTimeoutUnit ) {
180+ this .clusterDataTaskTimeoutUnit = clusterDataTaskTimeoutUnit ;
181+ }
182+
183+ public TimeUnit getClusterDataTaskTimeoutUnit () {
184+ return clusterDataTaskTimeoutUnit ;
185+ }
186+
187+ /**
188+ * Sets the timeout for a cluster data task (reading or writing cluster data). The default is 10 seconds.
189+ * <p>
190+ * Timeouts are useful when the cluster data root is on network storage, where I/O operations may occasionally block
191+ * for long or unpredictable periods.
192+ * <p>
193+ */
194+ public void setClusterDataTaskTimeout (long clusterDataTaskTimeout , TimeUnit clusterDataTaskTimeoutUnit ) {
195+ setClusterDataTaskTimeout (clusterDataTaskTimeout );
196+ setClusterDataTaskTimeoutUnit (clusterDataTaskTimeoutUnit );
197+ }
198+
130199 @ Override
131200 protected void doStop () throws Exception {
132201 super .doStop ();
@@ -142,6 +211,14 @@ protected void doStop() throws Exception {
142211
143212 executor = null ;
144213 }
214+
215+ if (clusterDataTaskExecutor != null ) {
216+ if (context != null ) {
217+ context .getExecutorServiceManager ().shutdown (clusterDataTaskExecutor );
218+ } else {
219+ clusterDataTaskExecutor .shutdown ();
220+ }
221+ }
145222 }
146223
147224 ScheduledExecutorService getExecutor () {
@@ -161,4 +238,19 @@ ScheduledExecutorService getExecutor() {
161238 internalLock .unlock ();
162239 }
163240 }
241+
242+ ExecutorService getClusterDataTaskExecutor () {
243+ Lock internalLock = getInternalLock ();
244+ internalLock .lock ();
245+ try {
246+ if (clusterDataTaskExecutor == null ) {
247+ final CamelContext context = ObjectHelper .notNull (getCamelContext (), "CamelContext" );
248+ clusterDataTaskExecutor = context .getExecutorServiceManager ().newFixedThreadPool (this ,
249+ "FileLockClusterDataTask-" + getId (), 5 );
250+ }
251+ return clusterDataTaskExecutor ;
252+ } finally {
253+ internalLock .unlock ();
254+ }
255+ }
164256}
0 commit comments