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

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


The following commit(s) were added to refs/heads/main by this push:
     new a303a1d70 Add Request Timeouts  (#1431)
a303a1d70 is described below

commit a303a1d70df3733f59914bcff62d3fe1a0fc3edc
Author: Richard Liu <[email protected]>
AuthorDate: Thu Apr 24 17:33:38 2025 -0500

    Add Request Timeouts  (#1431)
    
    * add timeout
    
    * add iceberg exception mapping
    
    * dont use quarkus bom, disable timeout
    
    * nits
---
 api/iceberg-service/build.gradle.kts                                  | 2 ++
 api/management-service/build.gradle.kts                               | 1 +
 api/polaris-catalog-service/build.gradle.kts                          | 2 ++
 gradle/libs.versions.toml                                             | 1 +
 quarkus/defaults/src/main/resources/application.properties            | 4 ++++
 quarkus/service/build.gradle.kts                                      | 1 +
 server-templates/api.mustache                                         | 3 +++
 service/common/build.gradle.kts                                       | 2 ++
 .../org/apache/polaris/service/exception/IcebergExceptionMapper.java  | 2 ++
 9 files changed, 18 insertions(+)

diff --git a/api/iceberg-service/build.gradle.kts 
b/api/iceberg-service/build.gradle.kts
index 596864e7f..a940a1b5e 100644
--- a/api/iceberg-service/build.gradle.kts
+++ b/api/iceberg-service/build.gradle.kts
@@ -45,6 +45,8 @@ dependencies {
   implementation("com.fasterxml.jackson.core:jackson-annotations")
   implementation("com.fasterxml.jackson.core:jackson-core")
   implementation("com.fasterxml.jackson.core:jackson-databind")
+
+  compileOnly(libs.microprofile.fault.tolerance.api)
 }
 
 openApiGenerate {
diff --git a/api/management-service/build.gradle.kts 
b/api/management-service/build.gradle.kts
index 78a3b5a71..9c59b0303 100644
--- a/api/management-service/build.gradle.kts
+++ b/api/management-service/build.gradle.kts
@@ -33,6 +33,7 @@ dependencies {
   compileOnly(libs.jakarta.annotation.api)
   compileOnly(libs.jakarta.inject.api)
   compileOnly(libs.jakarta.validation.api)
+  compileOnly(libs.microprofile.fault.tolerance.api)
   compileOnly(libs.swagger.annotations)
 
   implementation(libs.jakarta.servlet.api)
diff --git a/api/polaris-catalog-service/build.gradle.kts 
b/api/polaris-catalog-service/build.gradle.kts
index 6cd15f88a..77b801b98 100644
--- a/api/polaris-catalog-service/build.gradle.kts
+++ b/api/polaris-catalog-service/build.gradle.kts
@@ -71,6 +71,8 @@ dependencies {
   implementation("com.fasterxml.jackson.core:jackson-annotations")
   implementation("com.fasterxml.jackson.core:jackson-core")
   implementation("com.fasterxml.jackson.core:jackson-databind")
+
+  compileOnly(libs.microprofile.fault.tolerance.api)
 }
 
 openApiGenerate {
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 60ad6a680..25b2bc94f 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -73,6 +73,7 @@ javax-servlet-api = { module = 
"javax.servlet:javax.servlet-api", version = "4.0
 junit-bom = { module = "org.junit:junit-bom", version = "5.12.2" }
 logback-classic = { module = "ch.qos.logback:logback-classic", version = 
"1.5.18" }
 micrometer-bom = { module = "io.micrometer:micrometer-bom", version = "1.14.6" 
}
+microprofile-fault-tolerance-api = { module = 
"org.eclipse.microprofile.fault-tolerance:microprofile-fault-tolerance-api", 
version = "4.1.1" }
 mockito-core = { module = "org.mockito:mockito-core", version = "5.17.0" }
 mockito-junit-jupiter = { module = "org.mockito:mockito-junit-jupiter", 
version = "5.17.0" }
 opentelemetry-bom = { module = "io.opentelemetry:opentelemetry-bom", version = 
"1.49.0" }
diff --git a/quarkus/defaults/src/main/resources/application.properties 
b/quarkus/defaults/src/main/resources/application.properties
index 56b18ac3d..c7676b2ba 100644
--- a/quarkus/defaults/src/main/resources/application.properties
+++ b/quarkus/defaults/src/main/resources/application.properties
@@ -86,6 +86,10 @@ quarkus.otel.sdk.disabled=true
 
 quarkus.test.integration-test-profile=it
 
+quarkus.fault-tolerance.global.timeout.enabled=false
+# quarkus.fault-tolerance.global.timeout.unit=minutes
+# quarkus.fault-tolerance.global.timeout.value=10
+
 polaris.realm-context.type=default
 polaris.realm-context.realms=POLARIS
 polaris.realm-context.header-name=Polaris-Realm
diff --git a/quarkus/service/build.gradle.kts b/quarkus/service/build.gradle.kts
index 32d7ab421..eb729b020 100644
--- a/quarkus/service/build.gradle.kts
+++ b/quarkus/service/build.gradle.kts
@@ -55,6 +55,7 @@ dependencies {
   implementation("io.quarkus:quarkus-opentelemetry")
   implementation("io.quarkus:quarkus-security")
   implementation("io.quarkus:quarkus-smallrye-context-propagation")
+  implementation("io.quarkus:quarkus-smallrye-fault-tolerance")
 
   implementation(libs.jakarta.enterprise.cdi.api)
   implementation(libs.jakarta.inject.api)
diff --git a/server-templates/api.mustache b/server-templates/api.mustache
index c5f8123d8..d572abee1 100644
--- a/server-templates/api.mustache
+++ b/server-templates/api.mustache
@@ -57,6 +57,8 @@ import {{javaxPackage}}.inject.Inject;
 
 import org.apache.polaris.core.context.RealmContext;
 
+import org.eclipse.microprofile.faulttolerance.Timeout;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -108,6 +110,7 @@ public class {{classname}}  {
   @Produces({ {{#produces}}"{{{mediaType}}}"{{^-last}}, 
{{/-last}}{{/produces}} }){{/hasProduces}}{{#hasAuthMethods}}
   
{{#authMethods}}{{#isOAuth}}@RolesAllowed("**"){{/isOAuth}}{{/authMethods}}{{/hasAuthMethods}}
   @Timed("{{metricsPrefix}}.{{baseName}}.{{nickname}}")
+  @Timeout
   public Response {{nickname}}({{#isMultipart}}MultipartFormDataInput 
input,{{/isMultipart}}{{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{^isMultipart}}{{>formParams}},{{/isMultipart}}{{#isMultipart}}{{^isFormParam}},{{/isFormParam}}{{/isMultipart}}{{/allParams}}@Context
 @MeterTag(key="realm_id",expression="realmIdentifier") RealmContext 
realmContext,@Context SecurityContext securityContext) {
 {{! Don't log form or header params in case there are secrets, e.g., OAuth 
tokens }}
     LOGGER.atDebug().setMessage("Invoking {{baseName}} with params")
diff --git a/service/common/build.gradle.kts b/service/common/build.gradle.kts
index ca00893e0..d38838a85 100644
--- a/service/common/build.gradle.kts
+++ b/service/common/build.gradle.kts
@@ -90,6 +90,8 @@ dependencies {
   implementation("com.azure:azure-storage-blob")
   implementation("com.azure:azure-storage-file-datalake")
 
+  implementation(libs.microprofile.fault.tolerance.api)
+
   testImplementation(platform(libs.junit.bom))
   testImplementation("org.junit.jupiter:junit-jupiter")
   testImplementation(libs.assertj.core)
diff --git 
a/service/common/src/main/java/org/apache/polaris/service/exception/IcebergExceptionMapper.java
 
b/service/common/src/main/java/org/apache/polaris/service/exception/IcebergExceptionMapper.java
index 81bfbf21f..048da3f79 100644
--- 
a/service/common/src/main/java/org/apache/polaris/service/exception/IcebergExceptionMapper.java
+++ 
b/service/common/src/main/java/org/apache/polaris/service/exception/IcebergExceptionMapper.java
@@ -57,6 +57,7 @@ import 
org.apache.iceberg.exceptions.UnprocessableEntityException;
 import org.apache.iceberg.exceptions.ValidationException;
 import org.apache.iceberg.rest.responses.ErrorResponse;
 import org.apache.polaris.core.exceptions.FileIOUnknownHostException;
+import org.eclipse.microprofile.faulttolerance.exceptions.TimeoutException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.event.Level;
@@ -191,6 +192,7 @@ public class IcebergExceptionMapper implements 
ExceptionMapper<RuntimeException>
       case IllegalArgumentException e -> Status.BAD_REQUEST.getStatusCode();
       case UnsupportedOperationException e -> 
Status.NOT_ACCEPTABLE.getStatusCode();
       case WebApplicationException e -> e.getResponse().getStatus();
+      case TimeoutException e -> Status.REQUEST_TIMEOUT.getStatusCode();
       default -> Status.INTERNAL_SERVER_ERROR.getStatusCode();
     };
   }

Reply via email to