diff --git a/deploy/portainer/docker-compose.yml b/deploy/portainer/docker-compose.yml index 3e71b29a..0991992f 100644 --- a/deploy/portainer/docker-compose.yml +++ b/deploy/portainer/docker-compose.yml @@ -84,6 +84,15 @@ services: EVENT_FILE_STORE_ENABLED: ${EVENT_FILE_STORE_ENABLED:-true} EVENT_FILE_STORE_PATH: /event-store/ EVENT_FILE_STORE_ZONE_ID: ${EVENT_FILE_STORE_ZONE_ID:-Asia/Shanghai} + TDENGINE_HISTORY_ENABLED: ${TDENGINE_HISTORY_ENABLED:-true} + TDENGINE_HISTORY_DATABASE: ${TDENGINE_HISTORY_DATABASE:-vehicle_history} + TDENGINE_JDBC_URL: ${TDENGINE_JDBC_URL:-jdbc:TAOS-RS://tdengine:6041/vehicle_history} + TDENGINE_USERNAME: ${TDENGINE_USERNAME:-root} + TDENGINE_PASSWORD: ${TDENGINE_PASSWORD:-taosdata} + TDENGINE_MAX_POOL_SIZE: ${TDENGINE_MAX_POOL_SIZE:-32} + TDENGINE_MIN_IDLE: ${TDENGINE_MIN_IDLE:-0} + TDENGINE_CONNECTION_TIMEOUT_MILLIS: ${TDENGINE_CONNECTION_TIMEOUT_MILLIS:-5000} + TDENGINE_INITIALIZATION_FAIL_TIMEOUT_MILLIS: ${TDENGINE_INITIALIZATION_FAIL_TIMEOUT_MILLIS:--1} ports: - "${VEHICLE_HISTORY_HTTP_PORT:-20200}:20200" volumes: diff --git a/modules/apps/vehicle-history-app/src/main/resources/application.yml b/modules/apps/vehicle-history-app/src/main/resources/application.yml index 7f38d578..b6ec8d2e 100644 --- a/modules/apps/vehicle-history-app/src/main/resources/application.yml +++ b/modules/apps/vehicle-history-app/src/main/resources/application.yml @@ -69,6 +69,14 @@ lingniu: tdengine-history: enabled: ${TDENGINE_HISTORY_ENABLED:false} database: ${TDENGINE_HISTORY_DATABASE:vehicle_history} + jdbc-url: ${TDENGINE_JDBC_URL:jdbc:TAOS-RS://${TDENGINE_HOST:127.0.0.1}:${TDENGINE_PORT:6041}/${TDENGINE_HISTORY_DATABASE:vehicle_history}} + username: ${TDENGINE_USERNAME:root} + password: ${TDENGINE_PASSWORD:taosdata} + driver-class-name: ${TDENGINE_DRIVER_CLASS_NAME:com.taosdata.jdbc.rs.RestfulDriver} + maximum-pool-size: ${TDENGINE_MAX_POOL_SIZE:16} + minimum-idle: ${TDENGINE_MIN_IDLE:0} + connection-timeout-millis: ${TDENGINE_CONNECTION_TIMEOUT_MILLIS:5000} + initialization-fail-timeout-millis: ${TDENGINE_INITIALIZATION_FAIL_TIMEOUT_MILLIS:-1} event-history: enabled: true vehicle-state: diff --git a/modules/apps/vehicle-history-app/src/test/java/com/lingniu/ingest/historyapp/VehicleHistoryAppCompositionTest.java b/modules/apps/vehicle-history-app/src/test/java/com/lingniu/ingest/historyapp/VehicleHistoryAppCompositionTest.java index 0c54f2df..db4034d8 100644 --- a/modules/apps/vehicle-history-app/src/test/java/com/lingniu/ingest/historyapp/VehicleHistoryAppCompositionTest.java +++ b/modules/apps/vehicle-history-app/src/test/java/com/lingniu/ingest/historyapp/VehicleHistoryAppCompositionTest.java @@ -8,6 +8,8 @@ import com.lingniu.ingest.eventhistory.EventHistoryEnvelopeIngestor; import com.lingniu.ingest.eventhistory.Gb32960DecodedFrameService; import com.lingniu.ingest.eventhistory.Gb32960FrameController; import com.lingniu.ingest.eventhistory.config.EventHistoryAutoConfiguration; +import com.lingniu.ingest.eventhistory.Jt808LocationHistoryController; +import com.lingniu.ingest.eventhistory.TelemetryFieldHistoryController; import com.lingniu.ingest.protocol.gb32960.codec.Gb32960MessageDecoder; import com.lingniu.ingest.protocol.gb32960.config.Gb32960AutoConfiguration; import com.lingniu.ingest.protocol.gb32960.inbound.Gb32960NettyServer; @@ -78,6 +80,8 @@ class VehicleHistoryAppCompositionTest { assertThat(context).hasSingleBean(Gb32960MessageDecoder.class); assertThat(context).hasSingleBean(Gb32960DecodedFrameService.class); assertThat(context).hasSingleBean(Gb32960FrameController.class); + assertThat(context).hasSingleBean(Jt808LocationHistoryController.class); + assertThat(context).hasSingleBean(TelemetryFieldHistoryController.class); assertThat(context).doesNotHaveBean(Gb32960NettyServer.class); }); } diff --git a/modules/apps/vehicle-history-app/src/test/java/com/lingniu/ingest/historyapp/VehicleHistoryAppDefaultsTest.java b/modules/apps/vehicle-history-app/src/test/java/com/lingniu/ingest/historyapp/VehicleHistoryAppDefaultsTest.java index 38c47d24..92aa42ab 100644 --- a/modules/apps/vehicle-history-app/src/test/java/com/lingniu/ingest/historyapp/VehicleHistoryAppDefaultsTest.java +++ b/modules/apps/vehicle-history-app/src/test/java/com/lingniu/ingest/historyapp/VehicleHistoryAppDefaultsTest.java @@ -26,6 +26,16 @@ class VehicleHistoryAppDefaultsTest { .containsEntry("lingniu.ingest.event-file-store.enabled", "${EVENT_FILE_STORE_ENABLED:true}") .containsEntry("lingniu.ingest.tdengine-history.enabled", "${TDENGINE_HISTORY_ENABLED:false}") .containsEntry("lingniu.ingest.tdengine-history.database", "${TDENGINE_HISTORY_DATABASE:vehicle_history}") + .containsEntry( + "lingniu.ingest.tdengine-history.jdbc-url", + "${TDENGINE_JDBC_URL:jdbc:TAOS-RS://${TDENGINE_HOST:127.0.0.1}:${TDENGINE_PORT:6041}/${TDENGINE_HISTORY_DATABASE:vehicle_history}}") + .containsEntry("lingniu.ingest.tdengine-history.username", "${TDENGINE_USERNAME:root}") + .containsEntry("lingniu.ingest.tdengine-history.password", "${TDENGINE_PASSWORD:taosdata}") + .containsEntry( + "lingniu.ingest.tdengine-history.driver-class-name", + "${TDENGINE_DRIVER_CLASS_NAME:com.taosdata.jdbc.rs.RestfulDriver}") + .containsEntry("lingniu.ingest.tdengine-history.maximum-pool-size", "${TDENGINE_MAX_POOL_SIZE:16}") + .containsEntry("lingniu.ingest.tdengine-history.minimum-idle", "${TDENGINE_MIN_IDLE:0}") .containsEntry("lingniu.ingest.event-history.enabled", true) .containsEntry("lingniu.ingest.vehicle-state.enabled", false) .containsEntry("lingniu.ingest.vehicle-stat.enabled", false) diff --git a/modules/services/event-history-service/src/main/java/com/lingniu/ingest/eventhistory/config/EventHistoryAutoConfiguration.java b/modules/services/event-history-service/src/main/java/com/lingniu/ingest/eventhistory/config/EventHistoryAutoConfiguration.java index edcb8c12..339ff4a8 100644 --- a/modules/services/event-history-service/src/main/java/com/lingniu/ingest/eventhistory/config/EventHistoryAutoConfiguration.java +++ b/modules/services/event-history-service/src/main/java/com/lingniu/ingest/eventhistory/config/EventHistoryAutoConfiguration.java @@ -14,6 +14,7 @@ import com.lingniu.ingest.protocol.gb32960.codec.Gb32960MessageDecoder; import com.lingniu.ingest.protocol.gb32960.config.Gb32960AutoConfiguration; import com.lingniu.ingest.sink.archive.config.SinkArchiveAutoConfiguration; import com.lingniu.ingest.sink.archive.config.SinkArchiveProperties; +import com.lingniu.ingest.tdenginehistory.config.TdengineHistoryAutoConfiguration; import com.lingniu.ingest.tdenginehistory.TdengineHistoryReader; import com.lingniu.ingest.tdenginehistory.TdengineHistoryWriter; import org.springframework.boot.autoconfigure.AutoConfiguration; @@ -40,7 +41,11 @@ import java.nio.file.Path; * Kafka consumer 是否启动还取决于 {@code lingniu.ingest.sink.mq.consumer.enabled=true}。 */ @AutoConfiguration -@AutoConfigureAfter({Gb32960AutoConfiguration.class, SinkArchiveAutoConfiguration.class}) +@AutoConfigureAfter({ + Gb32960AutoConfiguration.class, + SinkArchiveAutoConfiguration.class, + TdengineHistoryAutoConfiguration.class +}) @ConditionalOnProperty(prefix = "lingniu.ingest.event-history", name = "enabled", havingValue = "true") public class EventHistoryAutoConfiguration { diff --git a/modules/sinks/tdengine-history-store/pom.xml b/modules/sinks/tdengine-history-store/pom.xml index 1612dcb0..f5798f52 100644 --- a/modules/sinks/tdengine-history-store/pom.xml +++ b/modules/sinks/tdengine-history-store/pom.xml @@ -24,6 +24,14 @@ org.springframework.boot spring-boot-autoconfigure + + com.taosdata.jdbc + taos-jdbcdriver + + + com.zaxxer + HikariCP + org.springframework.boot spring-boot-configuration-processor diff --git a/modules/sinks/tdengine-history-store/src/main/java/com/lingniu/ingest/tdenginehistory/config/TdengineHistoryAutoConfiguration.java b/modules/sinks/tdengine-history-store/src/main/java/com/lingniu/ingest/tdenginehistory/config/TdengineHistoryAutoConfiguration.java index b808308e..2d612fb3 100644 --- a/modules/sinks/tdengine-history-store/src/main/java/com/lingniu/ingest/tdenginehistory/config/TdengineHistoryAutoConfiguration.java +++ b/modules/sinks/tdengine-history-store/src/main/java/com/lingniu/ingest/tdenginehistory/config/TdengineHistoryAutoConfiguration.java @@ -6,6 +6,8 @@ import com.lingniu.ingest.tdenginehistory.TdengineHistoryReader; import com.lingniu.ingest.tdenginehistory.TdengineHistoryWriter; import com.lingniu.ingest.tdenginehistory.TdengineJdbcHistoryReader; import com.lingniu.ingest.tdenginehistory.TdengineJdbcHistoryWriter; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -39,6 +41,26 @@ public class TdengineHistoryAutoConfiguration { return new TdengineHistoryStatements(schema); } + @Bean + @ConditionalOnMissingBean(DataSource.class) + @ConditionalOnProperty( + prefix = "lingniu.ingest.tdengine-history", + name = "enabled", + havingValue = "true") + public DataSource tdengineDataSource(TdengineHistoryProperties properties) { + HikariConfig config = new HikariConfig(); + config.setPoolName("tdengine-history"); + config.setDriverClassName(properties.getDriverClassName()); + config.setJdbcUrl(properties.getJdbcUrl()); + config.setUsername(properties.getUsername()); + config.setPassword(properties.getPassword()); + config.setMaximumPoolSize(Math.max(1, properties.getMaximumPoolSize())); + config.setMinimumIdle(Math.max(0, Math.min(properties.getMinimumIdle(), properties.getMaximumPoolSize()))); + config.setConnectionTimeout(Math.max(250, properties.getConnectionTimeoutMillis())); + config.setInitializationFailTimeout(properties.getInitializationFailTimeoutMillis()); + return new HikariDataSource(config); + } + @Bean @ConditionalOnMissingBean @ConditionalOnBean(DataSource.class) diff --git a/modules/sinks/tdengine-history-store/src/main/java/com/lingniu/ingest/tdenginehistory/config/TdengineHistoryProperties.java b/modules/sinks/tdengine-history-store/src/main/java/com/lingniu/ingest/tdenginehistory/config/TdengineHistoryProperties.java index 03009ee2..d19a28eb 100644 --- a/modules/sinks/tdengine-history-store/src/main/java/com/lingniu/ingest/tdenginehistory/config/TdengineHistoryProperties.java +++ b/modules/sinks/tdengine-history-store/src/main/java/com/lingniu/ingest/tdenginehistory/config/TdengineHistoryProperties.java @@ -15,6 +15,25 @@ public class TdengineHistoryProperties { */ private String database = "vehicle_history"; + /** + * TDengine RESTful JDBC 地址。默认走 6041,部署时可用 TDENGINE_JDBC_URL 覆盖。 + */ + private String jdbcUrl; + + private String username = "root"; + + private String password = "taosdata"; + + private String driverClassName = "com.taosdata.jdbc.rs.RestfulDriver"; + + private int maximumPoolSize = 16; + + private int minimumIdle = 0; + + private long connectionTimeoutMillis = 5000; + + private long initializationFailTimeoutMillis = -1; + public boolean isEnabled() { return enabled; } @@ -30,4 +49,71 @@ public class TdengineHistoryProperties { public void setDatabase(String database) { this.database = database; } + + public String getJdbcUrl() { + if (jdbcUrl == null || jdbcUrl.isBlank()) { + return "jdbc:TAOS-RS://127.0.0.1:6041/" + database; + } + return jdbcUrl; + } + + public void setJdbcUrl(String jdbcUrl) { + this.jdbcUrl = jdbcUrl; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getDriverClassName() { + return driverClassName; + } + + public void setDriverClassName(String driverClassName) { + this.driverClassName = driverClassName; + } + + public int getMaximumPoolSize() { + return maximumPoolSize; + } + + public void setMaximumPoolSize(int maximumPoolSize) { + this.maximumPoolSize = maximumPoolSize; + } + + public int getMinimumIdle() { + return minimumIdle; + } + + public void setMinimumIdle(int minimumIdle) { + this.minimumIdle = minimumIdle; + } + + public long getConnectionTimeoutMillis() { + return connectionTimeoutMillis; + } + + public void setConnectionTimeoutMillis(long connectionTimeoutMillis) { + this.connectionTimeoutMillis = connectionTimeoutMillis; + } + + public long getInitializationFailTimeoutMillis() { + return initializationFailTimeoutMillis; + } + + public void setInitializationFailTimeoutMillis(long initializationFailTimeoutMillis) { + this.initializationFailTimeoutMillis = initializationFailTimeoutMillis; + } } diff --git a/modules/sinks/tdengine-history-store/src/test/java/com/lingniu/ingest/tdenginehistory/config/TdengineHistoryAutoConfigurationTest.java b/modules/sinks/tdengine-history-store/src/test/java/com/lingniu/ingest/tdenginehistory/config/TdengineHistoryAutoConfigurationTest.java index 58d8ba0e..8117f110 100644 --- a/modules/sinks/tdengine-history-store/src/test/java/com/lingniu/ingest/tdenginehistory/config/TdengineHistoryAutoConfigurationTest.java +++ b/modules/sinks/tdengine-history-store/src/test/java/com/lingniu/ingest/tdenginehistory/config/TdengineHistoryAutoConfigurationTest.java @@ -3,6 +3,7 @@ package com.lingniu.ingest.tdenginehistory.config; import com.lingniu.ingest.tdenginehistory.TdengineHistorySchema; import com.lingniu.ingest.tdenginehistory.TdengineHistoryReader; import com.lingniu.ingest.tdenginehistory.TdengineHistoryWriter; +import com.zaxxer.hikari.HikariDataSource; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -21,6 +22,7 @@ class TdengineHistoryAutoConfigurationTest { void staysOffByDefault() { contextRunner.run(context -> { assertThat(context).doesNotHaveBean(TdengineHistorySchema.class); + assertThat(context).doesNotHaveBean(DataSource.class); assertThat(context.getBean(TdengineHistoryProperties.class).isEnabled()).isFalse(); }); } @@ -53,4 +55,27 @@ class TdengineHistoryAutoConfigurationTest { .withPropertyValues("lingniu.ingest.tdengine-history.enabled=true") .run(context -> assertThat(context).hasSingleBean(TdengineHistoryReader.class)); } + + @Test + void createsTdengineDataSourceWhenEnabled() { + contextRunner + .withPropertyValues( + "lingniu.ingest.tdengine-history.enabled=true", + "lingniu.ingest.tdengine-history.jdbc-url=jdbc:TAOS-RS://tdengine:6041/vehicle_history", + "lingniu.ingest.tdengine-history.username=root", + "lingniu.ingest.tdengine-history.password=secret", + "lingniu.ingest.tdengine-history.maximum-pool-size=24", + "lingniu.ingest.tdengine-history.minimum-idle=3", + "lingniu.ingest.tdengine-history.initialization-fail-timeout-millis=-1") + .run(context -> { + assertThat(context).hasSingleBean(DataSource.class); + HikariDataSource dataSource = context.getBean(HikariDataSource.class); + assertThat(dataSource.getJdbcUrl()).isEqualTo("jdbc:TAOS-RS://tdengine:6041/vehicle_history"); + assertThat(dataSource.getUsername()).isEqualTo("root"); + assertThat(dataSource.getMaximumPoolSize()).isEqualTo(24); + assertThat(dataSource.getMinimumIdle()).isEqualTo(3); + assertThat(context).hasSingleBean(TdengineHistoryWriter.class); + assertThat(context).hasSingleBean(TdengineHistoryReader.class); + }); + } } diff --git a/pom.xml b/pom.xml index 3e20a6fa..f00e4a3e 100644 --- a/pom.xml +++ b/pom.xml @@ -65,6 +65,7 @@ 1.42.1 1.3.3 1.1.3 + 3.8.4 2.8.17 1.18.34 5.11.3 @@ -303,6 +304,11 @@ duckdb_jdbc ${duckdb.version} + + com.taosdata.jdbc + taos-jdbcdriver + ${taos-jdbcdriver.version} + org.springdoc springdoc-openapi-starter-webmvc-ui