This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push: new 1897eee905e CAMEL-18012: camel-main - Allow to configure extra shutdown timeoit (seconds) 1897eee905e is described below commit 1897eee905ea3b9e8b037448f5941b6d9363e51b Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Mon May 2 15:37:24 2022 +0200 CAMEL-18012: camel-main - Allow to configure extra shutdown timeoit (seconds) --- .../MainConfigurationPropertiesConfigurer.java | 6 +++++ .../camel-main-configuration-metadata.json | 3 ++- core/camel-main/src/main/docs/main.adoc | 5 +++-- .../camel/main/DefaultConfigurationProperties.java | 4 ++-- .../camel/main/DefaultMainShutdownStrategy.java | 13 ++++++----- .../camel/main/MainConfigurationProperties.java | 26 ++++++++++++++++++++++ .../apache/camel/main/MainShutdownStrategy.java | 11 +++++++++ .../java/org/apache/camel/main/MainSupport.java | 8 +++++++ .../camel/main/SimpleMainShutdownStrategy.java | 11 +++++++++ 9 files changed, 76 insertions(+), 11 deletions(-) diff --git a/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java b/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java index 6f87cd2efac..8d2e873c166 100644 --- a/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java +++ b/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java @@ -87,6 +87,8 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp case "ExchangeFactoryCapacity": target.setExchangeFactoryCapacity(property(camelContext, int.class, value)); return true; case "exchangefactorystatisticsenabled": case "ExchangeFactoryStatisticsEnabled": target.setExchangeFactoryStatisticsEnabled(property(camelContext, boolean.class, value)); return true; + case "extrashutdowntimeout": + case "ExtraShutdownTimeout": target.setExtraShutdownTimeout(property(camelContext, int.class, value)); return true; case "fileconfigurations": case "FileConfigurations": target.setFileConfigurations(property(camelContext, java.lang.String.class, value)); return true; case "globaloptions": @@ -316,6 +318,8 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp case "ExchangeFactoryCapacity": return int.class; case "exchangefactorystatisticsenabled": case "ExchangeFactoryStatisticsEnabled": return boolean.class; + case "extrashutdowntimeout": + case "ExtraShutdownTimeout": return int.class; case "fileconfigurations": case "FileConfigurations": return java.lang.String.class; case "globaloptions": @@ -546,6 +550,8 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp case "ExchangeFactoryCapacity": return target.getExchangeFactoryCapacity(); case "exchangefactorystatisticsenabled": case "ExchangeFactoryStatisticsEnabled": return target.isExchangeFactoryStatisticsEnabled(); + case "extrashutdowntimeout": + case "ExtraShutdownTimeout": return target.getExtraShutdownTimeout(); case "fileconfigurations": case "FileConfigurations": return target.getFileConfigurations(); case "globaloptions": diff --git a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json index 458a9ba74b0..4150355c981 100644 --- a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json +++ b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json @@ -46,6 +46,7 @@ { "name": "camel.main.exchangeFactory", "description": "Controls whether to pool (reuse) exchanges or create new exchanges (prototype). Using pooled will reduce JVM garbage collection overhead by avoiding to re-create Exchange instances per message each consumer receives. The default is prototype mode.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "default", "enum": [ "default", "prototype", " [...] { "name": "camel.main.exchangeFactoryCapacity", "description": "The capacity the pool (for each consumer) uses for storing exchanges. The default capacity is 100.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "integer", "javaType": "int", "defaultValue": 100 }, { "name": "camel.main.exchangeFactoryStatisticsEnabled", "description": "Configures whether statistics is enabled on exchange factory.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" }, + { "name": "camel.main.extraShutdownTimeout", "description": "Extra timeout in seconds to graceful shutdown Camel. When Camel is shutting down then Camel first shutdown all the routes (shutdownTimeout). Then additional services is shutdown (extraShutdownTimeout).", "sourceType": "org.apache.camel.main.MainConfigurationProperties", "type": "integer", "javaType": "int", "defaultValue": 15 }, { "name": "camel.main.fileConfigurations", "description": "Directory to load additional configuration files that contains configuration values that takes precedence over any other configuration. This can be used to refer to files that may have secret configuration that has been mounted on the file system for containers. You can specify a pattern to load from sub directories and a name pattern such as \/var\/app\/secret\/.properties, multiple directories can be separated by comma.", " [...] { "name": "camel.main.globalOptions", "description": "Sets global options that can be referenced in the camel context Important: This has nothing to do with property placeholders, and is just a plain set of key\/value pairs which are used to configure global options on CamelContext, such as a maximum debug logging length etc.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "object", "javaType": "java.util.Map" }, { "name": "camel.main.inflightRepositoryBrowseEnabled", "description": "Sets whether the inflight repository should allow browsing each inflight exchange. This is by default disabled as there is a very slight performance overhead when enabled.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" }, @@ -96,7 +97,7 @@ { "name": "camel.main.shutdownNowOnTimeout", "description": "Sets whether to force shutdown of all consumers when a timeout occurred and thus not all consumers was shutdown within that period. You should have good reasons to set this option to false as it means that the routes keep running and is halted abruptly when CamelContext has been shutdown.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": true }, { "name": "camel.main.shutdownRoutesInReverseOrder", "description": "Sets whether routes should be shutdown in reverse or the same order as they were started.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": true }, { "name": "camel.main.shutdownSuppressLoggingOnTimeout", "description": "Whether Camel should try to suppress logging during shutdown and timeout was triggered, meaning forced shutdown is happening. And during forced shutdown we want to avoid logging errors\/warnings et all in the logs as a side-effect of the forced timeout. Notice the suppress is a best effort as there may still be some logs coming from 3rd party libraries and whatnot, which Camel cannot control. This option is defa [...] - { "name": "camel.main.shutdownTimeout", "description": "Timeout in seconds to graceful shutdown Camel.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "integer", "javaType": "int", "defaultValue": 45 }, + { "name": "camel.main.shutdownTimeout", "description": "Timeout in seconds to graceful shutdown all the Camel routes.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "integer", "javaType": "int", "defaultValue": 45 }, { "name": "camel.main.sourceLocationEnabled", "description": "Whether to capture precise source location:line-number for all EIPs in Camel routes. Enabling this will impact parsing Java based routes (also Groovy, Kotlin, etc.) on startup as this uses JDK StackTraceElement to calculate the location from the Camel route, which comes with a performance cost. This only impact startup, not the performance of the routes at runtime.", "sourceType": "org.apache.camel.main.DefaultConfiguratio [...] { "name": "camel.main.startupRecorder", "description": "To use startup recorder for capturing execution time during starting Camel. The recorder can be one of: false (or off), logging, java-flight-recorder (or jfr).", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "string", "javaType": "java.lang.String", "enum": [ "false", "off", "java-flight-recorder", "jfr", "logging" ] }, { "name": "camel.main.startupRecorderDir", "description": "Directory to store the recording. By default the current directory will be used. Use false to turn off saving recording to disk.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, diff --git a/core/camel-main/src/main/docs/main.adoc b/core/camel-main/src/main/docs/main.adoc index b1c32ec176c..c4045f9f28c 100644 --- a/core/camel-main/src/main/docs/main.adoc +++ b/core/camel-main/src/main/docs/main.adoc @@ -18,7 +18,7 @@ The following tables lists all the options: // main options: START === Camel Main configurations -The camel.main supports 111 options, which are listed below. +The camel.main supports 112 options, which are listed below. [width="100%",cols="2,5,^1,2",options="header"] |=== @@ -56,6 +56,7 @@ The camel.main supports 111 options, which are listed below. | *camel.main.exchangeFactory* | Controls whether to pool (reuse) exchanges or create new exchanges (prototype). Using pooled will reduce JVM garbage collection overhead by avoiding to re-create Exchange instances per message each consumer receives. The default is prototype mode. | default | String | *camel.main.exchangeFactory{zwsp}Capacity* | The capacity the pool (for each consumer) uses for storing exchanges. The default capacity is 100. | 100 | int | *camel.main.exchangeFactory{zwsp}StatisticsEnabled* | Configures whether statistics is enabled on exchange factory. | false | boolean +| *camel.main.extraShutdown{zwsp}Timeout* | Extra timeout in seconds to graceful shutdown Camel. When Camel is shutting down then Camel first shutdown all the routes (shutdownTimeout). Then additional services is shutdown (extraShutdownTimeout). | 15 | int | *camel.main.fileConfigurations* | Directory to load additional configuration files that contains configuration values that takes precedence over any other configuration. This can be used to refer to files that may have secret configuration that has been mounted on the file system for containers. You can specify a pattern to load from sub directories and a name pattern such as /var/app/secret/.properties, multiple directories can be separated by comma. | | String | *camel.main.globalOptions* | Sets global options that can be referenced in the camel context Important: This has nothing to do with property placeholders, and is just a plain set of key/value pairs which are used to configure global options on CamelContext, such as a maximum debug logging length etc. | | Map | *camel.main.inflightRepository{zwsp}BrowseEnabled* | Sets whether the inflight repository should allow browsing each inflight exchange. This is by default disabled as there is a very slight performance overhead when enabled. | false | boolean @@ -106,7 +107,7 @@ The camel.main supports 111 options, which are listed below. | *camel.main.shutdownNowOn{zwsp}Timeout* | Sets whether to force shutdown of all consumers when a timeout occurred and thus not all consumers was shutdown within that period. You should have good reasons to set this option to false as it means that the routes keep running and is halted abruptly when CamelContext has been shutdown. | true | boolean | *camel.main.shutdownRoutesIn{zwsp}ReverseOrder* | Sets whether routes should be shutdown in reverse or the same order as they were started. | true | boolean | *camel.main.shutdownSuppress{zwsp}LoggingOnTimeout* | Whether Camel should try to suppress logging during shutdown and timeout was triggered, meaning forced shutdown is happening. And during forced shutdown we want to avoid logging errors/warnings et all in the logs as a side-effect of the forced timeout. Notice the suppress is a best effort as there may still be some logs coming from 3rd party libraries and whatnot, which Camel cannot control. This option is default false. | false | boolean -| *camel.main.shutdownTimeout* | Timeout in seconds to graceful shutdown Camel. | 45 | int +| *camel.main.shutdownTimeout* | Timeout in seconds to graceful shutdown all the Camel routes. | 45 | int | *camel.main.sourceLocation{zwsp}Enabled* | Whether to capture precise source location:line-number for all EIPs in Camel routes. Enabling this will impact parsing Java based routes (also Groovy, Kotlin, etc.) on startup as this uses JDK StackTraceElement to calculate the location from the Camel route, which comes with a performance cost. This only impact startup, not the performance of the routes at runtime. | false | boolean | *camel.main.startupRecorder* | To use startup recorder for capturing execution time during starting Camel. The recorder can be one of: false (or off), logging, java-flight-recorder (or jfr). | | String | *camel.main.startupRecorderDir* | Directory to store the recording. By default the current directory will be used. Use false to turn off saving recording to disk. | | String diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java index d416420f6e0..09fde0016bb 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java @@ -221,7 +221,7 @@ public abstract class DefaultConfigurationProperties<T> { } /** - * Timeout in seconds to graceful shutdown Camel. + * Timeout in seconds to graceful shutdown all the Camel routes. */ public void setShutdownTimeout(int shutdownTimeout) { this.shutdownTimeout = shutdownTimeout; @@ -1541,7 +1541,7 @@ public abstract class DefaultConfigurationProperties<T> { } /** - * Timeout in seconds to graceful shutdown Camel. + * Timeout in seconds to graceful shutdown all the Camel routes. */ public T withShutdownTimeout(int shutdownTimeout) { this.shutdownTimeout = shutdownTimeout; diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DefaultMainShutdownStrategy.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultMainShutdownStrategy.java index daa94253a07..3257aaa4e10 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/DefaultMainShutdownStrategy.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultMainShutdownStrategy.java @@ -89,15 +89,16 @@ public class DefaultMainShutdownStrategy extends SimpleMainShutdownStrategy { }; tracker.open(); - // use timeout from camel shutdown strategy and add 5 second extra to allow camel to shutdown graceful - long max = 5000 + main.getCamelContext().getShutdownStrategy().getTimeUnit() - .toMillis(main.getCamelContext().getShutdownStrategy().getTimeout()); + // use timeout from camel shutdown strategy and add extra to allow camel to shut down graceful + long max = TimeUnit.SECONDS.toMillis(getExtraShutdownTimeout()) + + main.getCamelContext().getShutdownStrategy().getTimeUnit() + .toMillis(main.getCamelContext().getShutdownStrategy().getTimeout()); int waits = 0; boolean done = false; StopWatch watch = new StopWatch(); while (!main.getCamelContext().isStopped() && !done && watch.taken() < max) { - String msg = "Waiting for CamelContext to graceful shutdown, elapsed: " - + TimeUtils.printDuration(watch.taken()); + String msg = "Waiting for CamelContext to graceful shutdown (max:" + + TimeUtils.printDuration(max) + ", elapsed:" + TimeUtils.printDuration(watch.taken()) + ")"; if (waits > 0 && waits % 5 == 0) { // do some info logging every 5th time LOG.info(msg); @@ -106,7 +107,7 @@ public class DefaultMainShutdownStrategy extends SimpleMainShutdownStrategy { } waits++; try { - // wait 1 sec and loop and log activity so we can see we are waiting + // wait 1 sec and loop and log activity, so we can see we are waiting done = latch.await(1000, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { // ignore diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java index 1a4295951f6..9ca67da6388 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java @@ -39,6 +39,7 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties< private boolean autoConfigurationFailFast = true; private boolean autoConfigurationLogSummary = true; private int durationHitExitCode; + private int extraShutdownTimeout = 15; private String basePackageScan; private boolean basePackageScanEnabled = true; private String routesCompileDirectory; @@ -395,6 +396,20 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties< this.durationHitExitCode = durationHitExitCode; } + public int getExtraShutdownTimeout() { + return extraShutdownTimeout; + } + + /** + * Extra timeout in seconds to graceful shutdown Camel. + * + * When Camel is shutting down then Camel first shutdown all the routes (shutdownTimeout). Then additional services + * is shutdown (extraShutdownTimeout). + */ + public void setExtraShutdownTimeout(int extraShutdownTimeout) { + this.extraShutdownTimeout = extraShutdownTimeout; + } + // getter and setters - configurations // -------------------------------------------------------------- @@ -598,6 +613,17 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties< return this; } + /** + * Extra timeout in seconds to graceful shutdown Camel. + * + * When Camel is shutting down then Camel first shutdown all the routes (shutdownTimeout). Then additional services + * is shutdown (extraShutdownTimeout). + */ + public MainConfigurationProperties withExtraShutdownTimeout(int extraShutdownTimeout) { + this.extraShutdownTimeout = extraShutdownTimeout; + return this; + } + /** * Package name to use as base (offset) for classpath scanning of {@link RouteBuilder}, and * {@link org.apache.camel.TypeConverter} classes. diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainShutdownStrategy.java b/core/camel-main/src/main/java/org/apache/camel/main/MainShutdownStrategy.java index 084ea6f9d80..1001d3f6823 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/MainShutdownStrategy.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/MainShutdownStrategy.java @@ -74,4 +74,15 @@ public interface MainShutdownStrategy { * This is used for restarting await with timeout. */ void restartAwait(); + + int getExtraShutdownTimeout(); + + /** + * Extra timeout in seconds to graceful shutdown Camel. + * + * When Camel is shutting down then Camel first shutdown all the routes (shutdownTimeout). Then additional services + * is shutdown (extraShutdownTimeout). + */ + void setExtraShutdownTimeout(int extraShutdownTimeout); + } diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java index 51fa028f357..32568e78dfc 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java @@ -69,6 +69,14 @@ public abstract class MainSupport extends BaseMainSupport { super.doInit(); } + @Override + protected void autoconfigure(CamelContext camelContext) throws Exception { + super.autoconfigure(camelContext); + + // additional main configuration after auto-configuration + shutdownStrategy.setExtraShutdownTimeout(configure().getExtraShutdownTimeout()); + } + /** * Runs this process with the given arguments, and will wait until completed, or the JVM terminates. */ diff --git a/core/camel-main/src/main/java/org/apache/camel/main/SimpleMainShutdownStrategy.java b/core/camel-main/src/main/java/org/apache/camel/main/SimpleMainShutdownStrategy.java index 3db20f9cce9..0b9ed328d6b 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/SimpleMainShutdownStrategy.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/SimpleMainShutdownStrategy.java @@ -36,6 +36,7 @@ public class SimpleMainShutdownStrategy implements MainShutdownStrategy { private final AtomicBoolean timeoutEnabled = new AtomicBoolean(); private final AtomicBoolean restarting = new AtomicBoolean(); private volatile CountDownLatch latch; + private int extraShutdownTimeout = 15; public SimpleMainShutdownStrategy() { this.completed = new AtomicBoolean(); @@ -104,4 +105,14 @@ public class SimpleMainShutdownStrategy implements MainShutdownStrategy { latch.countDown(); } } + + @Override + public int getExtraShutdownTimeout() { + return extraShutdownTimeout; + } + + @Override + public void setExtraShutdownTimeout(int extraShutdownTimeout) { + this.extraShutdownTimeout = extraShutdownTimeout; + } }