This is an automated email from the ASF dual-hosted git repository. bartmaer pushed a commit to branch 5670 in repository https://gitbox.apache.org/repos/asf/hop.git
commit a435ef3ecae31dfd35a2c7881cfab7a287e82ca2 Author: Bart Maertens <bart.maert...@know.bi> AuthorDate: Fri Sep 5 14:43:35 2025 +0200 additional retry options. fixes #5669 --- .../apache/hop/vfs/gs/GoogleStorageFileSystem.java | 22 ++- .../hop/vfs/gs/config/GoogleCloudConfig.java | 33 +++- .../hop/vfs/gs/config/GoogleCloudConfigPlugin.java | 220 +++++++++++++++++++++ .../gs/config/messages/messages_en_US.properties | 20 ++ 4 files changed, 288 insertions(+), 7 deletions(-) diff --git a/plugins/tech/google/src/main/java/org/apache/hop/vfs/gs/GoogleStorageFileSystem.java b/plugins/tech/google/src/main/java/org/apache/hop/vfs/gs/GoogleStorageFileSystem.java index 711d50f6bb..74a713b781 100644 --- a/plugins/tech/google/src/main/java/org/apache/hop/vfs/gs/GoogleStorageFileSystem.java +++ b/plugins/tech/google/src/main/java/org/apache/hop/vfs/gs/GoogleStorageFileSystem.java @@ -29,6 +29,8 @@ import org.apache.commons.vfs2.FileSystemException; import org.apache.commons.vfs2.FileSystemOptions; import org.apache.commons.vfs2.provider.AbstractFileName; import org.apache.commons.vfs2.provider.AbstractFileSystem; +import org.apache.hop.vfs.gs.config.GoogleCloudConfig; +import org.apache.hop.vfs.gs.config.GoogleCloudConfigSingleton; import org.threeten.bp.Duration; public class GoogleStorageFileSystem extends AbstractFileSystem { @@ -60,14 +62,22 @@ public class GoogleStorageFileSystem extends AbstractFileSystem { if (storage != null) { return storage; } + + GoogleCloudConfig config = GoogleCloudConfigSingleton.getConfig(); + RetrySettings retrySettings = StorageOptions.getDefaultRetrySettings().toBuilder() - // Set the max number of attempts to 10 (initial attempt plus 9 retries) - .setMaxAttempts(10) - // Set the backoff multiplier to 3.0 - .setRetryDelayMultiplier(3.0) - // Set the max duration of all attempts to 5 minutes - .setTotalTimeout(Duration.ofMinutes(5)) + .setMaxAttempts(Integer.parseInt(config.getMaxAttempts())) + .setInitialRetryDelay( + Duration.ofSeconds(Integer.parseInt(config.getInitialRetryDelay()))) + .setRetryDelayMultiplier(Double.parseDouble(config.getRetryDelayMultiplier())) + .setMaxRetryDelay(Duration.ofSeconds(Integer.parseInt(config.getMaxRetryDelay()))) + .setTotalTimeout(Duration.ofMinutes(Integer.parseInt(config.getTotalTimeout()))) + .setInitialRpcTimeout( + Duration.ofSeconds(Integer.parseInt(config.getInitialRpcTimeout()))) + .setRpcTimeoutMultiplier(Double.parseDouble(config.getRpcTimeoutMultiplier())) + // max RPC Timeout setting causes problems, disabled for now + // .setMaxRpcTimeout(Duration.ofSeconds(Integer.parseInt(config.getMaxRpcTimeout()))) .build(); StorageOptions.Builder optionsBuilder = StorageOptions.newBuilder(); diff --git a/plugins/tech/google/src/main/java/org/apache/hop/vfs/gs/config/GoogleCloudConfig.java b/plugins/tech/google/src/main/java/org/apache/hop/vfs/gs/config/GoogleCloudConfig.java index 98b77be0c6..c4a0023b3d 100644 --- a/plugins/tech/google/src/main/java/org/apache/hop/vfs/gs/config/GoogleCloudConfig.java +++ b/plugins/tech/google/src/main/java/org/apache/hop/vfs/gs/config/GoogleCloudConfig.java @@ -27,11 +27,42 @@ public class GoogleCloudConfig { public static final String HOP_CONFIG_GOOGLE_CLOUD_CONFIG_KEY = "googleCloud"; private String serviceAccountKeyFile; + private String maxAttempts; + private String initialRetryDelay; + private String retryDelayMultiplier; + private String maxRetryDelay; + private String totalTimeout; + private String initialRpcTimeout; + private String rpcTimeoutMultiplier; + private String maxRpcTimeout; + private String connectionTimeout; + private String readTimeout; - public GoogleCloudConfig() {} + public GoogleCloudConfig() { + maxAttempts = "6"; + initialRetryDelay = "1"; + retryDelayMultiplier = "2.0"; + maxRetryDelay = "32"; + totalTimeout = "50"; + initialRpcTimeout = "50"; + rpcTimeoutMultiplier = "1.0"; + maxRpcTimeout = "50"; + connectionTimeout = "20"; + readTimeout = "20"; + } public GoogleCloudConfig(GoogleCloudConfig config) { this(); serviceAccountKeyFile = config.serviceAccountKeyFile; + maxAttempts = config.maxAttempts; + initialRetryDelay = config.initialRetryDelay; + retryDelayMultiplier = config.retryDelayMultiplier; + maxRetryDelay = config.maxRetryDelay; + totalTimeout = config.totalTimeout; + initialRpcTimeout = config.initialRpcTimeout; + rpcTimeoutMultiplier = config.rpcTimeoutMultiplier; + maxRpcTimeout = config.maxRpcTimeout; + connectionTimeout = config.connectionTimeout; + readTimeout = config.readTimeout; } } diff --git a/plugins/tech/google/src/main/java/org/apache/hop/vfs/gs/config/GoogleCloudConfigPlugin.java b/plugins/tech/google/src/main/java/org/apache/hop/vfs/gs/config/GoogleCloudConfigPlugin.java index cbe425622e..5780006a3a 100644 --- a/plugins/tech/google/src/main/java/org/apache/hop/vfs/gs/config/GoogleCloudConfigPlugin.java +++ b/plugins/tech/google/src/main/java/org/apache/hop/vfs/gs/config/GoogleCloudConfigPlugin.java @@ -51,6 +51,26 @@ public class GoogleCloudConfigPlugin implements IConfigOptions, IGuiPluginCompos private static final String WIDGET_ID_GOOGLE_CLOUD_SERVICE_ACCOUNT_KEY_FILE = "10000-google-cloud-service-account-key-file"; + private static final String WIDGET_ID_GOOGLE_CLOUD_SERVICE_MAX_ATTEMPTS = + "10100-google-cloud-service-max-attempts"; + private static final String WIDGET_ID_GOOGLE_CLOUD_SERVICE_INITIAL_RETRY_DELAY = + "10200-google-cloud-service-initial-retry-delay"; + private static final String WIDGET_ID_GOOGLE_CLOUD_SERVICE_RETRY_DELAY_MULTIPLIER = + "10300-google-cloud-service-retry-delay-multiplier"; + private static final String WIDGET_ID_GOOGLE_CLOUD_SERVICE_MAX_RETRY_DELAY = + "10400-google-cloud-service-max-retry-delay"; + private static final String WIDGET_ID_GOOGLE_CLOUD_SERVICE_TOTAL_TIMEOUT = + "10500-google-cloud-service-total-timeout"; + private static final String WIDGET_ID_GOOGLE_CLOUD_SERVICE_INITIAL_RPC_TIMEOUT = + "10600-google-cloud-service-inital-rpc-timeout"; + private static final String WIDGET_ID_GOOGLE_CLOUD_SERVICE_RPC_TIMEOUT_MULTIPLIER = + "10700-google-cloud-service-rpc-timeout-multiplier"; + private static final String WIDGET_ID_GOOGLE_CLOUD_SERVICE_MAX_RPC_TIMEOUT = + "10800-google-cloud-service-max-rpc-timeout"; + private static final String WIDGET_ID_GOOGLE_CLOUD_SERVICE_CONNECT_TIMEOUT = + "10900-google-cloud-service-connect-timeout"; + private static final String WIDGET_ID_GOOGLE_CLOUD_SERVICE_READ_TIMEOUT = + "1100-google-cloud-service-read-timeout"; @GuiWidgetElement( id = WIDGET_ID_GOOGLE_CLOUD_SERVICE_ACCOUNT_KEY_FILE, @@ -64,6 +84,96 @@ public class GoogleCloudConfigPlugin implements IConfigOptions, IGuiPluginCompos description = "Configure the path to a Google Cloud service account JSON key file") private String serviceAccountKeyFile; + @GuiWidgetElement( + id = WIDGET_ID_GOOGLE_CLOUD_SERVICE_MAX_ATTEMPTS, + parentId = ConfigPluginOptionsTab.GUI_WIDGETS_PARENT_ID, + type = GuiElementType.TEXT, + variables = true, + label = "i18n::GoogleCloudPlugin.MaxAttempts.Label", + toolTip = "i18n::GoogleCloudPlugin.MaxAttempts.Description") + private String maxAttempts; + + @GuiWidgetElement( + id = WIDGET_ID_GOOGLE_CLOUD_SERVICE_INITIAL_RETRY_DELAY, + parentId = ConfigPluginOptionsTab.GUI_WIDGETS_PARENT_ID, + type = GuiElementType.TEXT, + variables = true, + label = "i18n::GoogleCloudPlugin.InitialRetryDelay.Label", + toolTip = "i18n::GoogleCloudPlugin.InitialRetryDelay.Description") + private String initialRetryDelay; + + @GuiWidgetElement( + id = WIDGET_ID_GOOGLE_CLOUD_SERVICE_RETRY_DELAY_MULTIPLIER, + parentId = ConfigPluginOptionsTab.GUI_WIDGETS_PARENT_ID, + type = GuiElementType.TEXT, + variables = true, + label = "i18n::GoogleCloudPlugin.RetryDelayMultiplier.Label", + toolTip = "i18n::GoogleCloudPlugin.RetryDelayMultiplier.Description") + private String retryDelayMultiplier; + + @GuiWidgetElement( + id = WIDGET_ID_GOOGLE_CLOUD_SERVICE_MAX_RETRY_DELAY, + parentId = ConfigPluginOptionsTab.GUI_WIDGETS_PARENT_ID, + type = GuiElementType.TEXT, + variables = true, + label = "i18n::GoogleCloudPlugin.MaxRetryDelay.Label", + toolTip = "i18n::GoogleCloudPlugin.MaxRetryDelay.Description") + private String maxRetryDelay; + + @GuiWidgetElement( + id = WIDGET_ID_GOOGLE_CLOUD_SERVICE_TOTAL_TIMEOUT, + parentId = ConfigPluginOptionsTab.GUI_WIDGETS_PARENT_ID, + type = GuiElementType.TEXT, + variables = true, + label = "i18n::GoogleCloudPlugin.TotalTimeout.Label", + toolTip = "i18n::GoogleCloudPlugin.TotalTimeout.Description") + private String totalTimeout; + + @GuiWidgetElement( + id = WIDGET_ID_GOOGLE_CLOUD_SERVICE_INITIAL_RPC_TIMEOUT, + parentId = ConfigPluginOptionsTab.GUI_WIDGETS_PARENT_ID, + type = GuiElementType.TEXT, + variables = true, + label = "i18n::GoogleCloudPlugin.InitialRpcTimeout.Label", + toolTip = "i18n::GoogleCloudPlugin.InitialRpcTimeout.Description") + private String initialRpcTimeout; + + @GuiWidgetElement( + id = WIDGET_ID_GOOGLE_CLOUD_SERVICE_RPC_TIMEOUT_MULTIPLIER, + parentId = ConfigPluginOptionsTab.GUI_WIDGETS_PARENT_ID, + type = GuiElementType.TEXT, + variables = true, + label = "i18n::GoogleCloudPlugin.RpcTimeoutMultiplier.Label", + toolTip = "i18n::GoogleCloudPlugin.RpcTimeoutMultiplier.Description") + private String rpcTimeoutMultiplier; + + @GuiWidgetElement( + id = WIDGET_ID_GOOGLE_CLOUD_SERVICE_MAX_RPC_TIMEOUT, + parentId = ConfigPluginOptionsTab.GUI_WIDGETS_PARENT_ID, + type = GuiElementType.TEXT, + variables = true, + label = "i18n::GoogleCloudPlugin.MaxRpcTimeout.Label", + toolTip = "i18n::GoogleCloudPlugin.MaxRpcTimeout.Description") + private String maxRpcTimeout; + + @GuiWidgetElement( + id = WIDGET_ID_GOOGLE_CLOUD_SERVICE_CONNECT_TIMEOUT, + parentId = ConfigPluginOptionsTab.GUI_WIDGETS_PARENT_ID, + type = GuiElementType.TEXT, + variables = true, + label = "i18n::GoogleCloudPlugin.ConnectTimeout.Label", + toolTip = "i18n::GoogleCloudPlugin.ConnectTimeout.Description") + private String connectTimeout; + + @GuiWidgetElement( + id = WIDGET_ID_GOOGLE_CLOUD_SERVICE_READ_TIMEOUT, + parentId = ConfigPluginOptionsTab.GUI_WIDGETS_PARENT_ID, + type = GuiElementType.TEXT, + variables = true, + label = "i18n::GoogleCloudPlugin.ReadTimeout.Label", + toolTip = "i18n::GoogleCloudPlugin.ReadTimeout.Description") + private String readTimeout; + /** * Gets instance * @@ -74,6 +184,16 @@ public class GoogleCloudConfigPlugin implements IConfigOptions, IGuiPluginCompos GoogleCloudConfig config = GoogleCloudConfigSingleton.getConfig(); instance.serviceAccountKeyFile = config.getServiceAccountKeyFile(); + instance.maxAttempts = config.getMaxAttempts(); + instance.initialRetryDelay = config.getInitialRetryDelay(); + instance.retryDelayMultiplier = config.getRetryDelayMultiplier(); + instance.maxRetryDelay = config.getMaxRetryDelay(); + instance.totalTimeout = config.getTotalTimeout(); + instance.initialRpcTimeout = config.getInitialRpcTimeout(); + instance.rpcTimeoutMultiplier = config.getRpcTimeoutMultiplier(); + instance.maxRpcTimeout = config.getMaxRpcTimeout(); + instance.connectTimeout = config.getConnectionTimeout(); + instance.readTimeout = config.getReadTimeout(); return instance; } @@ -92,6 +212,67 @@ public class GoogleCloudConfigPlugin implements IConfigOptions, IGuiPluginCompos "The Google Cloud service account JSON jey file is set to '" + serviceAccountKeyFile + "'"); + + changed = true; + } + + if (maxAttempts != null) { + config.setMaxAttempts(maxAttempts); + log.logBasic("Google Cloud service max attempts set to " + maxAttempts); + changed = true; + } + + if (initialRetryDelay != null) { + config.setInitialRetryDelay(initialRetryDelay); + log.logBasic("Google Cloud service initialRetryDelay set to " + initialRetryDelay); + changed = true; + } + + if (retryDelayMultiplier != null) { + config.setRetryDelayMultiplier(retryDelayMultiplier); + log.logBasic("Google Cloud service retryDelayMultiplier set to " + retryDelayMultiplier); + changed = true; + } + + if (maxRetryDelay != null) { + config.setMaxRetryDelay(maxRetryDelay); + log.logBasic("Google Cloud service maxRetryDelay set to " + maxRetryDelay); + changed = true; + } + + if (totalTimeout != null) { + config.setTotalTimeout(totalTimeout); + log.logBasic("Google Cloud service totalTimeout set to " + totalTimeout); + changed = true; + } + + if (initialRpcTimeout != null) { + config.setInitialRpcTimeout(initialRpcTimeout); + log.logBasic("Google Cloud service initialRpcTimeout set to " + initialRpcTimeout); + changed = true; + } + + if (rpcTimeoutMultiplier != null) { + config.setRpcTimeoutMultiplier(rpcTimeoutMultiplier); + log.logBasic("Google Cloud service rpcTimeoutMultiplier set to " + rpcTimeoutMultiplier); + changed = true; + } + + if (maxRpcTimeout != null) { + config.setMaxRpcTimeout(maxRpcTimeout); + log.logBasic("Google Cloud service maxRpcTimeout set to " + maxRpcTimeout); + changed = true; + } + + if (connectTimeout != null) { + config.setConnectionTimeout(connectTimeout); + log.logBasic("Google Cloud service connectTimeout set to " + connectTimeout); + changed = true; + } + + if (readTimeout != null) { + config.setReadTimeout(readTimeout); + log.logBasic("Google Cloud service readTimeout set to " + readTimeout); changed = true; } @@ -131,6 +312,45 @@ public class GoogleCloudConfigPlugin implements IConfigOptions, IGuiPluginCompos serviceAccountKeyFile = ((TextVar) control).getText(); GoogleCloudConfigSingleton.getConfig().setServiceAccountKeyFile(serviceAccountKeyFile); break; + case WIDGET_ID_GOOGLE_CLOUD_SERVICE_MAX_ATTEMPTS: + maxAttempts = ((TextVar) control).getText(); + GoogleCloudConfigSingleton.getConfig().setMaxAttempts(maxAttempts); + break; + case WIDGET_ID_GOOGLE_CLOUD_SERVICE_INITIAL_RETRY_DELAY: + initialRetryDelay = ((TextVar) control).getText(); + GoogleCloudConfigSingleton.getConfig().setInitialRetryDelay(initialRetryDelay); + break; + case WIDGET_ID_GOOGLE_CLOUD_SERVICE_RETRY_DELAY_MULTIPLIER: + retryDelayMultiplier = ((TextVar) control).getText(); + GoogleCloudConfigSingleton.getConfig().setRetryDelayMultiplier(retryDelayMultiplier); + break; + case WIDGET_ID_GOOGLE_CLOUD_SERVICE_MAX_RETRY_DELAY: + maxRetryDelay = ((TextVar) control).getText(); + GoogleCloudConfigSingleton.getConfig().setMaxRetryDelay(maxRetryDelay); + break; + case WIDGET_ID_GOOGLE_CLOUD_SERVICE_TOTAL_TIMEOUT: + totalTimeout = ((TextVar) control).getText(); + GoogleCloudConfigSingleton.getConfig().setTotalTimeout(totalTimeout); + break; + case WIDGET_ID_GOOGLE_CLOUD_SERVICE_INITIAL_RPC_TIMEOUT: + initialRpcTimeout = ((TextVar) control).getText(); + GoogleCloudConfigSingleton.getConfig().setInitialRpcTimeout(initialRpcTimeout); + break; + case WIDGET_ID_GOOGLE_CLOUD_SERVICE_RPC_TIMEOUT_MULTIPLIER: + rpcTimeoutMultiplier = ((TextVar) control).getText(); + GoogleCloudConfigSingleton.getConfig().setRpcTimeoutMultiplier(rpcTimeoutMultiplier); + case WIDGET_ID_GOOGLE_CLOUD_SERVICE_MAX_RPC_TIMEOUT: + maxRpcTimeout = ((TextVar) control).getText(); + GoogleCloudConfigSingleton.getConfig().setMaxRpcTimeout(maxRpcTimeout); + break; + case WIDGET_ID_GOOGLE_CLOUD_SERVICE_CONNECT_TIMEOUT: + connectTimeout = ((TextVar) control).getText(); + GoogleCloudConfigSingleton.getConfig().setConnectionTimeout(connectTimeout); + break; + case WIDGET_ID_GOOGLE_CLOUD_SERVICE_READ_TIMEOUT: + readTimeout = ((TextVar) control).getText(); + GoogleCloudConfigSingleton.getConfig().setReadTimeout(readTimeout); + break; } } // Save the project... diff --git a/plugins/tech/google/src/main/resources/org/apache/hop/vfs/gs/config/messages/messages_en_US.properties b/plugins/tech/google/src/main/resources/org/apache/hop/vfs/gs/config/messages/messages_en_US.properties index 4469d8b7be..99813db674 100644 --- a/plugins/tech/google/src/main/resources/org/apache/hop/vfs/gs/config/messages/messages_en_US.properties +++ b/plugins/tech/google/src/main/resources/org/apache/hop/vfs/gs/config/messages/messages_en_US.properties @@ -20,3 +20,23 @@ GoogleCloudPlugin.AccountKeyFile.Description=The path to a Google Cloud service account JSON key file GoogleCloudPlugin.AccountKeyFile.Label=Account key file GoogleCloudPlugin.GuiPlugin.Description=Google Cloud +GoogleCloudPlugin.MaxAttempts.Label=Max number of attempts +GoogleCloudPlugin.MaxAttempts.Description=Max number of attempts +GoogleCloudPlugin.InitialRetryDelay.Label=Initial retry delay +GoogleCloudPlugin.InitialRetryDelay.Description=Initial retry delay +GoogleCloudPlugin.RetryDelayMultiplier.Label=Retry delay multiplier +GoogleCloudPlugin.RetryDelayMultiplier.Description=Retry delay multiplier +GoogleCloudPlugin.MaxRetryDelay.Label=Maximum retry delay +GoogleCloudPlugin.MaxRetryDelay.Description=Maximum retry delay +GoogleCloudPlugin.TotalTimeout.Label=Total Timeout +GoogleCloudPlugin.TotalTimeout.Description=Total Timeout +GoogleCloudPlugin.InitialRpcTimeout.Label=Initial RPC Timeout +GoogleCloudPlugin.InitialRpcTimeout.Description=Initial RPC Timeout +GoogleCloudPlugin.RpcTimeoutMultiplier.Label=RPC Timeout Multiplier +GoogleCloudPlugin.RpcTimeoutMultiplier.Description=RPC Timeout Multiplier +GoogleCloudPlugin.MaxRpcTimeout.Label=Max RPC Timeout +GoogleCloudPlugin.MaxRpcTimeout.Description=Max RPC Timeout +GoogleCloudPlugin.ConnectTimeout.Label=Connect Timeout +GoogleCloudPlugin.ConnectTimeout.Description=Connect Timeout +GoogleCloudPlugin.ReadTimeout.Label=Read Timeout +GoogleCloudPlugin.ReadTimeout.Description=Read Timeout \ No newline at end of file