diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dao/Dao.java b/cwms-data-api/src/main/java/cwms/cda/data/dao/Dao.java index 19dc4c41d..0fc01a960 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dao/Dao.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dao/Dao.java @@ -26,11 +26,14 @@ import static usace.cwms.db.jooq.codegen.tables.AV_DB_CHANGE_LOG.AV_DB_CHANGE_LOG; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; import cwms.cda.data.dto.CwmsDTO; import java.sql.Connection; import java.sql.SQLException; import java.util.List; import java.util.Optional; +import java.util.concurrent.TimeUnit; import org.jooq.DSLContext; import org.jooq.SQLDialect; import org.jooq.impl.DSL; @@ -42,16 +45,18 @@ public abstract class Dao { public static final int CWMS_21_1_1 = 210101; public static final int CWMS_23_03_16 = 230316; + public static final String PROP_BASE = "cwms.cda.data.dao.dao"; + public static final String VERSION_NAME = "version"; + private static final Cache versionCache = CacheBuilder.newBuilder() + .maximumSize(Integer.getInteger(PROP_BASE + "." + VERSION_NAME + + ".maxSize", 8)) + .expireAfterWrite(Integer.getInteger(PROP_BASE + "." + VERSION_NAME + + ".expireAfterSeconds", 300), TimeUnit.SECONDS) + .build(); + @SuppressWarnings("unused") protected DSLContext dsl; - /* We only need this once per instance of a DAO. - * would probably be good to cache at a larger level but - * this does strike a balance between performance and picking - * up new database features in real-time. - */ - private Integer theDbVersion = null; - protected Dao(DSLContext dsl) { this.dsl = dsl; } @@ -66,14 +71,22 @@ private static String getVersion(DSLContext dsl) { } public int getDbVersion() { - if (theDbVersion == null) { - String version = getVersion(dsl); - String[] parts = version.split("\\."); - theDbVersion = Integer.parseInt(parts[0]) * 10000 - + Integer.parseInt(parts[1]) * 100 - + Integer.parseInt(parts[2]); + Integer cachedValue = versionCache.getIfPresent(VERSION_NAME); + if (cachedValue == null) { + int newValue = versionAsInteger(getVersion(dsl)); + versionCache.put(VERSION_NAME, newValue); + return newValue; + } else { + return cachedValue; } - return theDbVersion; // the unboxing is still cheaper than a database call (the logging was nuts.) + } + + private static int versionAsInteger(String version) { + String[] parts = version.split("\\."); + + return Integer.parseInt(parts[0]) * 10000 + + Integer.parseInt(parts[1]) * 100 + + Integer.parseInt(parts[2]); } diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesDaoImpl.java b/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesDaoImpl.java index c2f13a5cf..0c71b2805 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesDaoImpl.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dao/TimeSeriesDaoImpl.java @@ -29,6 +29,8 @@ import cwms.cda.data.dto.VerticalDatumInfo; import cwms.cda.data.dto.catalog.CatalogEntry; import cwms.cda.data.dto.catalog.TimeseriesCatalogEntry; +import cwms.cda.formatters.FormattingException; +import cwms.cda.formatters.xml.XMLv1; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.Connection; @@ -52,8 +54,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; -import cwms.cda.formatters.FormattingException; -import cwms.cda.formatters.xml.XMLv1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jooq.CommonTableExpression; @@ -75,9 +75,6 @@ import org.jooq.TableField; import org.jooq.TableLike; import org.jooq.TableOnConditionStep; -import org.jooq.WindowOrderByStep; -import org.jooq.WindowSpecification; -import org.jooq.WindowSpecificationRowsStep; import org.jooq.conf.ParamType; import org.jooq.exception.DataAccessException; import org.jooq.impl.DSL; @@ -501,7 +498,7 @@ public Catalog getTimeSeriesCatalog(String page, int pageSize, CatalogRequestPar String cursorOffice = null; Catalog.CatalogPage catPage = null; if (page == null || page.isEmpty()) { - CommonTableExpression limiter = buildWithClause(inputParams, buildWhereConditions(inputParams), new ArrayList(), pageSize, true); + CommonTableExpression limiter = buildWithClause(inputParams, buildWhereConditions(inputParams), new ArrayList<>(), pageSize, true); SelectJoinStep> totalQuery = dsl.with(limiter) .select(countDistinct(limiter.field(AV_CWMS_TS_ID.AV_CWMS_TS_ID.TS_CODE))) .from(limiter); @@ -554,6 +551,7 @@ public Catalog getTimeSeriesCatalog(String page, int pageSize, CatalogRequestPar logger.info(() -> overallQuery.getSQL(ParamType.INLINED)); Result result = overallQuery.fetch(); + int dbVersion = this.getDbVersion(); Map tsIdExtentMap = new LinkedHashMap<>(); result.forEach(row -> { String officeTsId = row.get(AV_CWMS_TS_ID.AV_CWMS_TS_ID.DB_OFFICE_ID) @@ -566,7 +564,7 @@ public Catalog getTimeSeriesCatalog(String page, int pageSize, CatalogRequestPar .units(row.get(AV_CWMS_TS_ID.AV_CWMS_TS_ID.UNIT_ID)) .interval(row.get(AV_CWMS_TS_ID.AV_CWMS_TS_ID.INTERVAL_ID)) .intervalOffset(row.get(AV_CWMS_TS_ID.AV_CWMS_TS_ID.INTERVAL_UTC_OFFSET)); - if (this.getDbVersion() > Dao.CWMS_21_1_1) { + if (dbVersion > Dao.CWMS_21_1_1) { builder.timeZone(row.get("TIME_ZONE_ID", String.class)); } if (params.isIncludeExtents()) {