From b963f11995a3d7afec3a54670e8f4a394210f8d8 Mon Sep 17 00:00:00 2001
From: Brandon Clayton <bclayton@usgs.gov>
Date: Wed, 24 Apr 2024 10:51:22 -0600
Subject: [PATCH] lambda test

---
 gradle.properties                             |  2 +-
 gradle/dependencies.gradle                    |  3 +
 gradle/spotbugs.gradle                        |  2 +
 .../earthquake/nshmp/www/PrimingResource.java | 56 +++++++++++++------
 .../earthquake/nshmp/www/ServletUtil.java     | 25 ++++++---
 .../nshmp/www/SwaggerController.java          | 53 +++++++++++++++---
 .../nshmp/www/hazard/DisaggService.java       |  2 +-
 .../nshmp/www/hazard/HazardController.java    |  4 ++
 .../nshmp/www/hazard/HazardService.java       |  2 +-
 .../nshmp/www/source/FeaturesService.java     |  4 +-
 .../nshmp/www/source/LogicTreesService.java   |  6 +-
 .../nshmp/www/source/MfdsService.java         |  4 +-
 .../nshmp/www/source/RateService.java         |  4 +-
 .../nshmp/www/source/SourceService.java       |  2 +-
 src/main/resources/application.yml            |  2 +-
 15 files changed, 123 insertions(+), 48 deletions(-)

diff --git a/gradle.properties b/gradle.properties
index bdaf57b68..33598f7ff 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -11,6 +11,6 @@ nshmpLibVersion = 1.5.4
 nshmpUtilsJavaVersion = 0.4.0
 openApiVersion = 4.0.0
 shadowVersion = 7.1.2
-spotbugsVersion = 4.7.0
+spotbugsVersion = 4.7.3
 spotlessVersion = 6.0.4
 swaggerParserVersion = 2.1.21
diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle
index d2b2fdb46..5c0b8b387 100644
--- a/gradle/dependencies.gradle
+++ b/gradle/dependencies.gradle
@@ -35,4 +35,7 @@ dependencies {
   testImplementation "io.micronaut.test:micronaut-test-junit5"
   testImplementation "io.micronaut.test:micronaut-test-spock"
   testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine"
+
+  spotbugs("com.github.spotbugs:spotbugs:${spotbugsVersion}")
+  spotbugsPlugins("software.amazon.lambda.snapstart:aws-lambda-snapstart-java-rules:0.2.1")
 }
diff --git a/gradle/spotbugs.gradle b/gradle/spotbugs.gradle
index 51f1a63a2..6a40a2ce7 100644
--- a/gradle/spotbugs.gradle
+++ b/gradle/spotbugs.gradle
@@ -8,4 +8,6 @@ apply plugin: "com.github.spotbugs"
 spotbugs {
   excludeFilter = file("${projectDir}/gradle/spotbugs-filter.xml")
   effort = "max"
+  ignoreFailures.set(false)
+  showStackTraces.set(true)
 }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/PrimingResource.java b/src/main/java/gov/usgs/earthquake/nshmp/www/PrimingResource.java
index c852f32a8..da2ef9e14 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/PrimingResource.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/PrimingResource.java
@@ -1,6 +1,15 @@
 package gov.usgs.earthquake.nshmp.www;
 
+import java.net.URI;
+import java.net.URL;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
 import java.util.Optional;
+import java.util.concurrent.Executors;
 import java.util.logging.Logger;
 
 import org.crac.Context;
@@ -8,6 +17,7 @@ import org.crac.Resource;
 
 import com.amazonaws.serverless.proxy.internal.testutils.MockLambdaContext;
 import com.amazonaws.serverless.proxy.model.AwsProxyRequest;
+import com.google.common.util.concurrent.MoreExecutors;
 
 import io.micronaut.context.annotation.Value;
 import io.micronaut.crac.OrderedResource;
@@ -20,6 +30,9 @@ import jakarta.inject.Singleton;
 @Singleton
 public class PrimingResource implements OrderedResource {
 
+  @Value("${nshmp-haz.model-path}")
+  private Path modelPath;
+
   @Value("${nshmp-haz.context-path}")
   String contextPath;
 
@@ -27,6 +40,7 @@ public class PrimingResource implements OrderedResource {
   public void beforeCheckpoint(Context<? extends Resource> context) throws Exception {
     Logger log = Logger.getAnonymousLogger();
     log.info("Before checkpoint");
+    ServletUtil.model(ServletUtil.loadModel(modelPath));
 
     Optional<String> location = Optional.ofNullable(System.getenv("TEST_LOCATION"));
 
@@ -35,38 +49,43 @@ public class PrimingResource implements OrderedResource {
           getAwsProxyRequest(contextPath + "/hazard"),
           new MockLambdaContext());
 
-      log.info("Test location");
-      if (location.isPresent()) {
-        log.info("Location: " + location.get());
-        handler.handleRequest(
-            getAwsProxyRequest(contextPath + "/hazard" + location.get()),
-            new MockLambdaContext());
-      }
+      // log.info("Test location");
+      // if (location.isPresent()) {
+      //   log.info("Location: " + location.get());
+      //   handler.handleRequest(
+      //       getAwsProxyRequest(contextPath + "/hazard" + location.get()),
+      //       new MockLambdaContext());
+      // }
 
       // handler.handleRequest(
-      //     getAwsProxyRequest(contextPath + "/probability"),
-      //     new MockLambdaContext());
+      // getAwsProxyRequest(contextPath + "/probability"),
+      // new MockLambdaContext());
 
       // handler.handleRequest(
-      //     getAwsProxyRequest(contextPath + "/rate"),
-      //     new MockLambdaContext());
+      // getAwsProxyRequest(contextPath + "/rate"),
+      // new MockLambdaContext());
 
       // handler.handleRequest(
-      //     getAwsProxyRequest(contextPath + "/disagg"),
-      //     new MockLambdaContext());
+      // getAwsProxyRequest(contextPath + "/disagg"),
+      // new MockLambdaContext());
 
       // handler.handleRequest(
-      //     getAwsProxyRequest(contextPath + "/map"),
-      //     new MockLambdaContext());
+      // getAwsProxyRequest(contextPath + "/map"),
+      // new MockLambdaContext());
 
       // handler.handleRequest(
-      //     getAwsProxyRequest(contextPath),
-      //     new MockLambdaContext());
+      // getAwsProxyRequest(contextPath),
+      // new MockLambdaContext());
     }
   }
 
   @Override
-  public void afterRestore(Context<? extends Resource> context) throws Exception {}
+  public void afterRestore(Context<? extends Resource> context) throws Exception {
+    ServletUtil.CALC_EXECUTOR.shutdown();
+    ServletUtil.TASK_EXECUTOR.shutdown();
+    ServletUtil.CALC_EXECUTOR = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(ServletUtil.THREAD_COUNT));
+    ServletUtil.TASK_EXECUTOR = Executors.newSingleThreadExecutor();
+  }
 
   private static AwsProxyRequest getAwsProxyRequest(String path) {
 
@@ -75,4 +94,5 @@ public class PrimingResource implements OrderedResource {
     awsProxyRequest.setPath(path);
     return awsProxyRequest;
   }
+
 }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/ServletUtil.java b/src/main/java/gov/usgs/earthquake/nshmp/www/ServletUtil.java
index 02203d880..a3d1a7b08 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/ServletUtil.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/ServletUtil.java
@@ -11,6 +11,7 @@ import java.nio.file.FileSystems;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.HashMap;
+import java.util.Optional;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
@@ -52,8 +53,8 @@ public class ServletUtil {
   public static final Gson GSON;
   public static final Gson GSON2;
 
-  public static final ListeningExecutorService CALC_EXECUTOR;
-  public static final ExecutorService TASK_EXECUTOR;
+  public static ListeningExecutorService CALC_EXECUTOR;
+  public static ExecutorService TASK_EXECUTOR;
 
   public static final int THREAD_COUNT;
 
@@ -62,6 +63,8 @@ public class ServletUtil {
 
   private static HazardModel HAZARD_MODEL;
 
+  private static Optional<String> awsRuntime = Optional.ofNullable(System.getenv("AWS_LAMBDA_RUNTIME_API"));
+
   static {
     THREAD_COUNT = getRuntime().availableProcessors();
     CALC_EXECUTOR = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(THREAD_COUNT));
@@ -89,13 +92,17 @@ public class ServletUtil {
 
   }
 
+  static void model(HazardModel model) {
+    HAZARD_MODEL = model;
+  }
+
   public static HazardModel model() {
     return HAZARD_MODEL;
   }
 
   @EventListener
   void shutdown(ShutdownEvent event) {
-    Logger log = LoggerFactory.getLogger(getClass());
+    var log = java.util.logging.Logger.getAnonymousLogger();
 
     log.info("on shutdown");
     CALC_EXECUTOR.shutdown();
@@ -104,13 +111,17 @@ public class ServletUtil {
 
   @EventListener
   void startup(StartupEvent event) {
-    Logger log = LoggerFactory.getLogger(getClass());
+    var log = java.util.logging.Logger.getAnonymousLogger();
 
-    log.info("on startup: load model");
-    HAZARD_MODEL = loadModel(modelPath);
+    log.info("on startup");
+
+    if (!awsRuntime.isPresent()) {
+      log.info("not aws");
+      HAZARD_MODEL = loadModel(modelPath);
+    }
   }
 
-  private HazardModel loadModel(Path path) {
+  static HazardModel loadModel(Path path) {
     URL url;
     URI uri;
     String uriString;
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/SwaggerController.java b/src/main/java/gov/usgs/earthquake/nshmp/www/SwaggerController.java
index 41e30233b..f629ac32d 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/SwaggerController.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/SwaggerController.java
@@ -1,14 +1,14 @@
 package gov.usgs.earthquake.nshmp.www;
 
+import java.math.BigDecimal;
 import java.util.List;
+import java.util.logging.Logger;
 
-import org.slf4j.LoggerFactory;
-
+import gov.usgs.earthquake.nshmp.geo.Location;
 import gov.usgs.earthquake.nshmp.model.HazardModel;
 import gov.usgs.earthquake.nshmp.www.source.FeaturesService;
 
 import io.micronaut.http.HttpRequest;
-import io.micronaut.http.HttpResponse;
 import io.micronaut.http.MediaType;
 import io.micronaut.http.annotation.Controller;
 import io.micronaut.http.annotation.Get;
@@ -16,6 +16,7 @@ import io.swagger.v3.core.util.Yaml;
 import io.swagger.v3.oas.annotations.Hidden;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.parameters.Parameter;
 import io.swagger.v3.parser.OpenAPIV3Parser;
 import jakarta.inject.Inject;
 
@@ -35,24 +36,28 @@ public class SwaggerController {
   private NshmpMicronautServlet servlet;
 
   @Get(produces = MediaType.TEXT_EVENT_STREAM)
-  public HttpResponse<String> doGet(HttpRequest<?> request) {
+  public String doGet(HttpRequest<?> request) {
     try {
       var model = ServletUtil.model();
       var openApi = getOpenAPI(request, model);
-      return HttpResponse.ok(Yaml.pretty(openApi));
+      return Yaml.pretty(openApi);
     } catch (Exception e) {
-      return ServletUtil.error(
-          LoggerFactory.getLogger("Swagger"),
-          e, "Swagger", request.getUri().toString());
+      return e.getMessage();
+      // return ServletUtil.error(
+      // LoggerFactory.getLogger("Swagger"),
+      // e, "Swagger", request.getUri().getPath());
     }
   }
 
   private OpenAPI getOpenAPI(
       HttpRequest<?> request,
       HazardModel model) {
+    Logger log = Logger.getAnonymousLogger();
     var openApi = new OpenAPIV3Parser().read("META-INF/swagger/nshmp-haz.yml");
     var bounds = model.bounds();
-    SwaggerUtils.addLocationBounds(openApi, bounds.min, bounds.max);
+    log.info("a");
+    // SwaggerUtils.addLocationBounds(openApi, bounds.min, bounds.max);
+    log.info("b");
     var components = openApi.getComponents();
     var schemas = components.getSchemas();
     SwaggerUtils.siteClassSchema(schemas, List.copyOf(model.siteClasses().keySet()));
@@ -68,4 +73,34 @@ public class SwaggerController {
     return openApi;
   }
 
+  public static OpenAPI addLocationBounds(OpenAPI openApi, Location min, Location max) {
+    openApi.getPaths().values().stream()
+        .flatMap(path -> path.readOperations().stream())
+        .forEach(operation -> addLocationBounds(operation.getParameters(), min, max));
+
+    return openApi;
+  }
+
+  public static List<Parameter> addLocationBounds(
+      List<Parameter> parameters,
+      Location min,
+      Location max) {
+    var latitudeDescription = String.format(" [%s, %s]", min.latitude, max.latitude);
+    var longtudeDescription = String.format(" [%s, %s]", min.longitude, max.longitude);
+
+    parameters.forEach(parameter -> {
+      if (parameter.getName().equals("latitude")) {
+        parameter.setDescription(parameter.getDescription() + latitudeDescription);
+        parameter.getSchema().setMinimum(BigDecimal.valueOf(min.latitude));
+        parameter.getSchema().setMaximum(BigDecimal.valueOf(max.latitude));
+      } else if (parameter.getName().equals("longitude")) {
+        parameter.setDescription(parameter.getDescription() + longtudeDescription);
+        parameter.getSchema().setMinimum(BigDecimal.valueOf(min.longitude));
+        parameter.getSchema().setMaximum(BigDecimal.valueOf(max.longitude));
+      }
+    });
+
+    return parameters;
+  }
+
 }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggService.java
index a0bdb002b..5775030b5 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggService.java
@@ -79,7 +79,7 @@ public final class DisaggService {
   }
 
   static HttpResponse<String> getMetadata(HttpRequest<?> request) {
-    var url = request.getUri().toString();
+    var url = request.getUri().getPath();
     var usage = new Metadata(ServletUtil.model());
     var response = ResponseBody.usage()
         .name(NAME)
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardController.java b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardController.java
index b78c842ce..7a3263671 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardController.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardController.java
@@ -1,6 +1,7 @@
 package gov.usgs.earthquake.nshmp.www.hazard;
 
 import java.util.Set;
+import java.util.logging.Logger;
 
 import gov.usgs.earthquake.nshmp.gmm.Imt;
 import gov.usgs.earthquake.nshmp.www.NshmpMicronautServlet;
@@ -102,6 +103,9 @@ public class HazardController {
           defaultValue = "false") @Nullable Boolean maxdir,
       @QueryValue @Nullable Set<Imt> imt) {
     try {
+      Logger log = Logger.getAnonymousLogger();
+      log.info("Hazard call");
+      log.info("Thread count: " + ServletUtil.THREAD_COUNT);
       Set<Imt> imts = HazardService.readImts(http);
       HazardService.Request request = new HazardService.Request(
           http, longitude, latitude, vs30, imts, truncate, maxdir);
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardService.java
index 42830d66d..8cedf4fd8 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardService.java
@@ -63,7 +63,7 @@ public final class HazardService {
   private static final String TOTAL_KEY = "Total";
 
   public static HttpResponse<String> getMetadata(HttpRequest<?> request) {
-    var url = request.getUri().toString();
+    var url = request.getUri().getPath();
     var usage = new Metadata(ServletUtil.model());
     var body = ResponseBody.usage()
         .name(NAME)
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/source/FeaturesService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/source/FeaturesService.java
index a7ce6e542..1477b2204 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/source/FeaturesService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/source/FeaturesService.java
@@ -91,7 +91,7 @@ public class FeaturesService {
   private static HttpResponse<String> processResponse(
       HttpRequest<?> request,
       RequestData requestData) {
-    var url = request.getUri().toString();
+    var url = request.getUri().getPath();
 
     var features = requestData.featureType == FeatureType.ALL
         ? Models.features(ServletUtil.model(), Optional.empty())
@@ -120,7 +120,7 @@ public class FeaturesService {
   }
 
   private static HttpResponse<String> metadata(HttpRequest<?> request) {
-    var url = request.getUri().toString();
+    var url = request.getUri().getPath();
     var metadata = new Metadata(ServletUtil.model());
     var response = ResponseBody.usage()
         .name(NAME)
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/source/LogicTreesService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/source/LogicTreesService.java
index 3d961d8bd..ce64d2d41 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/source/LogicTreesService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/source/LogicTreesService.java
@@ -27,7 +27,7 @@ public class LogicTreesService {
   static final Logger LOG = LoggerFactory.getLogger(LogicTreesService.class);
 
   public static HttpResponse<String> getMetadata(HttpRequest<?> request) {
-    var url = request.getUri().toString();
+    var url = request.getUri().getPath();
     var metadata = new Metadata(ServletUtil.model());
     var response = ResponseBody.usage()
         .name(NAME)
@@ -40,7 +40,7 @@ public class LogicTreesService {
   }
 
   public static HttpResponse<String> getFeatureTree(HttpRequest<?> request, Integer id) {
-    var url = request.getUri().toString();
+    var url = request.getUri().getPath();
     var featureTree = Models.features(ServletUtil.model(), id);
     var requestData = new RequestData(id);
     var response = ResponseBody.success()
@@ -54,7 +54,7 @@ public class LogicTreesService {
   }
 
   public static HttpResponse<String> getMfdTree(HttpRequest<?> request, Integer id) {
-    var url = request.getUri().toString();
+    var url = request.getUri().getPath();
     var mfdTree = Models.tree(ServletUtil.model(), id);
     var requestData = new RequestData(id);
     var response = ResponseBody.success()
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/source/MfdsService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/source/MfdsService.java
index 4acad3ac3..b445bb90d 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/source/MfdsService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/source/MfdsService.java
@@ -32,7 +32,7 @@ public class MfdsService {
   static final Logger LOG = LoggerFactory.getLogger(LogicTreesService.class);
 
   public static HttpResponse<String> getMetadata(HttpRequest<?> request) {
-    var url = request.getUri().toString();
+    var url = request.getUri().getPath();
     var metadata = new Metadata(ServletUtil.model());
     var response = ResponseBody.usage()
         .name(NAME)
@@ -49,7 +49,7 @@ public class MfdsService {
       TectonicSetting setting,
       Optional<SourceType> type) {
 
-    var url = request.getUri().toString();
+    var url = request.getUri().getPath();
     var mfd = Models.mfd(ServletUtil.model(), setting, type);
     var requestData = new RequestData(setting, type.orElse(null));
     var response = ResponseBody.success()
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/source/RateService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/source/RateService.java
index 0907b014c..69916006e 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/source/RateService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/source/RateService.java
@@ -332,7 +332,7 @@ public final class RateService {
   }
 
   public static HttpResponse<String> getRateMetadata(HttpRequest<?> request) {
-    var url = request.getUri().toString();
+    var url = request.getUri().getPath();
     var usage = new Metadata(ServletUtil.model());
     var body = ResponseBody.usage()
         .name(NAME_RATE)
@@ -346,7 +346,7 @@ public final class RateService {
   }
 
   public static HttpResponse<String> getProbMetadata(HttpRequest<?> request) {
-    var url = request.getUri().toString();
+    var url = request.getUri().getPath();
     var usage = new ProbMetadata(ServletUtil.model());
     var body = ResponseBody.usage()
         .name(NAME_PROBABILITY)
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/source/SourceService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/source/SourceService.java
index dd1bc2ed9..2cae2b306 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/source/SourceService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/source/SourceService.java
@@ -35,7 +35,7 @@ public class SourceService {
   static final Logger LOG = LoggerFactory.getLogger(SourceService.class);
 
   static HttpResponse<String> getMetadata(HttpRequest<?> request) {
-    var url = request.getUri().toString();
+    var url = request.getUri().getPath();
     var response = ResponseBody.usage()
         .name(NAME)
         .url(url)
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index bda22c4f5..5d7de4be4 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -21,5 +21,5 @@ nshmp-haz:
   # To specify the model to use:
   #     java -jar build/libs/nshmp-haz.jar --model=<path/to/model>
   #
-  model-path: ${MODEL:nshms/nshm-conus-2018}
+  model-path: ${MODEL:nshms/nshm-alaska-2007}
   context-path: ${CONTEXT_PATH:}
-- 
GitLab