refactor: expose kafka sink configuration
This commit is contained in:
@@ -99,9 +99,8 @@ lingniu:
|
||||
table-name: ${VEHICLE_IDENTITY_MYSQL_TABLE:vehicle_identity_bindings}
|
||||
initialize-schema: ${VEHICLE_IDENTITY_MYSQL_INITIALIZE_SCHEMA:true}
|
||||
sink:
|
||||
mq:
|
||||
kafka:
|
||||
enabled: ${KAFKA_ENABLED:true}
|
||||
type: kafka
|
||||
bootstrap-servers: ${KAFKA_BROKERS:114.55.58.251:9092}
|
||||
compression-type: zstd
|
||||
linger-ms: 20
|
||||
|
||||
@@ -11,9 +11,9 @@ import com.lingniu.ingest.session.config.SessionCoreAutoConfiguration;
|
||||
import com.lingniu.ingest.sink.archive.ArchiveStore;
|
||||
import com.lingniu.ingest.sink.archive.RawArchiveEventSink;
|
||||
import com.lingniu.ingest.sink.archive.config.SinkArchiveAutoConfiguration;
|
||||
import com.lingniu.ingest.sink.mq.KafkaEventSink;
|
||||
import com.lingniu.ingest.sink.mq.KafkaEnvelopeDeadLetterSink;
|
||||
import com.lingniu.ingest.sink.mq.SinkMqAutoConfiguration;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaEventSink;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaEnvelopeDeadLetterSink;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaSinkAutoConfiguration;
|
||||
import org.apache.kafka.clients.producer.KafkaProducer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
@@ -31,7 +31,7 @@ class Gb32960IngestAppCompositionTest {
|
||||
IngestCoreAutoConfiguration.class,
|
||||
SessionCoreAutoConfiguration.class,
|
||||
VehicleIdentityAutoConfiguration.class,
|
||||
SinkMqAutoConfiguration.class,
|
||||
KafkaSinkAutoConfiguration.class,
|
||||
SinkArchiveAutoConfiguration.class,
|
||||
Gb32960AutoConfiguration.class))
|
||||
.withAllowBeanDefinitionOverriding(true)
|
||||
@@ -43,10 +43,9 @@ class Gb32960IngestAppCompositionTest {
|
||||
"lingniu.ingest.gb32960.port=0",
|
||||
"lingniu.ingest.identity.store=mysql",
|
||||
"lingniu.ingest.identity.mysql.initialize-schema=false",
|
||||
"lingniu.ingest.sink.mq.enabled=true",
|
||||
"lingniu.ingest.sink.mq.type=kafka",
|
||||
"lingniu.ingest.sink.mq.bootstrap-servers=localhost:9092",
|
||||
"lingniu.ingest.sink.mq.consumer.enabled=false",
|
||||
"lingniu.ingest.sink.kafka.enabled=true",
|
||||
"lingniu.ingest.sink.kafka.bootstrap-servers=localhost:9092",
|
||||
"lingniu.ingest.sink.kafka.consumer.enabled=false",
|
||||
"lingniu.ingest.sink.archive.enabled=true",
|
||||
"lingniu.ingest.sink.archive.path=target/test-archive-gb32960",
|
||||
"lingniu.ingest.event-history.enabled=false");
|
||||
|
||||
@@ -15,6 +15,8 @@ class Gb32960IngestAppDefaultsTest {
|
||||
@Test
|
||||
void applicationDefaultsKeepGb32960IngestAsTcpKafkaProducerOnly() throws IOException {
|
||||
Properties properties = applicationProperties();
|
||||
String legacyKafkaPrefix = "lingniu.ingest.sink." + "mq.";
|
||||
String kafkaTypeProperty = "lingniu.ingest.sink.kafka." + "type";
|
||||
|
||||
assertThat(properties)
|
||||
.containsEntry("spring.application.name", "gb32960-ingest-app")
|
||||
@@ -40,8 +42,8 @@ class Gb32960IngestAppDefaultsTest {
|
||||
"Hyundai")
|
||||
.containsEntry("lingniu.ingest.gb32960.vendor-extensions[0].match.platform-accounts[1]",
|
||||
"YueJin")
|
||||
.containsEntry("lingniu.ingest.sink.mq.enabled", "${KAFKA_ENABLED:true}")
|
||||
.containsEntry("lingniu.ingest.sink.mq.consumer.enabled", false)
|
||||
.containsEntry("lingniu.ingest.sink.kafka.enabled", "${KAFKA_ENABLED:true}")
|
||||
.containsEntry("lingniu.ingest.sink.kafka.consumer.enabled", false)
|
||||
.containsEntry("lingniu.ingest.sink.archive.enabled", "${SINK_ARCHIVE_ENABLED:true}")
|
||||
.containsEntry("lingniu.ingest.sink.archive.path", "${SINK_ARCHIVE_PATH:./archive/}")
|
||||
.containsEntry("lingniu.ingest.session.store", "${SESSION_STORE:redis}")
|
||||
@@ -55,7 +57,9 @@ class Gb32960IngestAppDefaultsTest {
|
||||
assertThat(properties.stringPropertyNames())
|
||||
.noneMatch(name -> name.startsWith("lingniu.ingest.event-file-store."))
|
||||
.noneMatch(name -> name.startsWith("lingniu.ingest.vehicle-state."))
|
||||
.noneMatch(name -> name.startsWith("lingniu.ingest.vehicle-stat."));
|
||||
.noneMatch(name -> name.startsWith("lingniu.ingest.vehicle-stat."))
|
||||
.noneMatch(name -> name.startsWith(legacyKafkaPrefix))
|
||||
.noneMatch(name -> name.equals(kafkaTypeProperty));
|
||||
assertThat(applicationYaml())
|
||||
.doesNotContain("event-file-store:")
|
||||
.doesNotContain("vehicle-state:")
|
||||
|
||||
@@ -63,9 +63,8 @@ lingniu:
|
||||
table-name: ${VEHICLE_IDENTITY_MYSQL_TABLE:vehicle_identity_bindings}
|
||||
initialize-schema: ${VEHICLE_IDENTITY_MYSQL_INITIALIZE_SCHEMA:true}
|
||||
sink:
|
||||
mq:
|
||||
kafka:
|
||||
enabled: ${KAFKA_ENABLED:true}
|
||||
type: kafka
|
||||
bootstrap-servers: ${KAFKA_BROKERS:114.55.58.251:9092}
|
||||
compression-type: zstd
|
||||
linger-ms: 20
|
||||
|
||||
@@ -11,9 +11,9 @@ import com.lingniu.ingest.session.config.SessionCoreAutoConfiguration;
|
||||
import com.lingniu.ingest.sink.archive.ArchiveStore;
|
||||
import com.lingniu.ingest.sink.archive.RawArchiveEventSink;
|
||||
import com.lingniu.ingest.sink.archive.config.SinkArchiveAutoConfiguration;
|
||||
import com.lingniu.ingest.sink.mq.KafkaEnvelopeDeadLetterSink;
|
||||
import com.lingniu.ingest.sink.mq.KafkaEventSink;
|
||||
import com.lingniu.ingest.sink.mq.SinkMqAutoConfiguration;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaEnvelopeDeadLetterSink;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaEventSink;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaSinkAutoConfiguration;
|
||||
import org.apache.kafka.clients.producer.KafkaProducer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
@@ -31,7 +31,7 @@ class Jt808IngestAppCompositionTest {
|
||||
IngestCoreAutoConfiguration.class,
|
||||
SessionCoreAutoConfiguration.class,
|
||||
VehicleIdentityAutoConfiguration.class,
|
||||
SinkMqAutoConfiguration.class,
|
||||
KafkaSinkAutoConfiguration.class,
|
||||
SinkArchiveAutoConfiguration.class,
|
||||
Jt808AutoConfiguration.class))
|
||||
.withAllowBeanDefinitionOverriding(true)
|
||||
@@ -42,10 +42,9 @@ class Jt808IngestAppCompositionTest {
|
||||
"lingniu.ingest.jt808.port=0",
|
||||
"lingniu.ingest.identity.store=mysql",
|
||||
"lingniu.ingest.identity.mysql.initialize-schema=false",
|
||||
"lingniu.ingest.sink.mq.enabled=true",
|
||||
"lingniu.ingest.sink.mq.type=kafka",
|
||||
"lingniu.ingest.sink.mq.bootstrap-servers=localhost:9092",
|
||||
"lingniu.ingest.sink.mq.consumer.enabled=false",
|
||||
"lingniu.ingest.sink.kafka.enabled=true",
|
||||
"lingniu.ingest.sink.kafka.bootstrap-servers=localhost:9092",
|
||||
"lingniu.ingest.sink.kafka.consumer.enabled=false",
|
||||
"lingniu.ingest.sink.archive.enabled=true",
|
||||
"lingniu.ingest.sink.archive.path=target/test-archive-jt808",
|
||||
"lingniu.ingest.event-history.enabled=false");
|
||||
|
||||
@@ -28,11 +28,11 @@ class Jt808IngestAppDefaultsTest {
|
||||
.containsEntry("server.port", "${HTTP_PORT:20400}")
|
||||
.containsEntry("lingniu.ingest.jt808.enabled", true)
|
||||
.containsEntry("lingniu.ingest.jt808.port", "${JT808_PORT:808}")
|
||||
.containsEntry("lingniu.ingest.sink.mq.enabled", "${KAFKA_ENABLED:true}")
|
||||
.containsEntry("lingniu.ingest.sink.mq.consumer.enabled", false)
|
||||
.containsEntry("lingniu.ingest.sink.mq.topics.realtime", "${KAFKA_TOPIC_JT808_EVENT:vehicle.event.jt808.v1}")
|
||||
.containsEntry("lingniu.ingest.sink.mq.topics.raw-archive", "${KAFKA_TOPIC_JT808_RAW:vehicle.raw.jt808.v1}")
|
||||
.containsEntry("lingniu.ingest.sink.mq.topics.dlq", "${KAFKA_TOPIC_JT808_DLQ:vehicle.dlq.jt808.v1}")
|
||||
.containsEntry("lingniu.ingest.sink.kafka.enabled", "${KAFKA_ENABLED:true}")
|
||||
.containsEntry("lingniu.ingest.sink.kafka.consumer.enabled", false)
|
||||
.containsEntry("lingniu.ingest.sink.kafka.topics.realtime", "${KAFKA_TOPIC_JT808_EVENT:vehicle.event.jt808.v1}")
|
||||
.containsEntry("lingniu.ingest.sink.kafka.topics.raw-archive", "${KAFKA_TOPIC_JT808_RAW:vehicle.raw.jt808.v1}")
|
||||
.containsEntry("lingniu.ingest.sink.kafka.topics.dlq", "${KAFKA_TOPIC_JT808_DLQ:vehicle.dlq.jt808.v1}")
|
||||
.containsEntry("lingniu.ingest.session.store", "${SESSION_STORE:redis}")
|
||||
.containsEntry("lingniu.ingest.identity.store", "${VEHICLE_IDENTITY_STORE:mysql}")
|
||||
.containsEntry("lingniu.ingest.identity.mysql.table-name",
|
||||
|
||||
@@ -37,9 +37,8 @@ lingniu:
|
||||
gb32960:
|
||||
enabled: false
|
||||
sink:
|
||||
mq:
|
||||
kafka:
|
||||
enabled: ${KAFKA_ENABLED:true}
|
||||
type: kafka
|
||||
bootstrap-servers: ${KAFKA_BROKERS:114.55.58.251:9092}
|
||||
topics:
|
||||
realtime: ${KAFKA_TOPIC_JT808_EVENT:vehicle.event.jt808.v1}
|
||||
|
||||
@@ -2,9 +2,9 @@ package com.lingniu.ingest.analyticsapp;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeConsumerProcessor;
|
||||
import com.lingniu.ingest.sink.mq.KafkaEnvelopeDeadLetterSink;
|
||||
import com.lingniu.ingest.sink.mq.KafkaEventSink;
|
||||
import com.lingniu.ingest.sink.mq.SinkMqAutoConfiguration;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaEnvelopeDeadLetterSink;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaEventSink;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaSinkAutoConfiguration;
|
||||
import com.lingniu.ingest.vehiclestat.JdbcVehicleStatMetricRepository;
|
||||
import com.lingniu.ingest.vehiclestat.VehicleStatController;
|
||||
import com.lingniu.ingest.vehiclestat.VehicleStatEnvelopeIngestor;
|
||||
@@ -28,17 +28,16 @@ class VehicleAnalyticsAppCompositionTest {
|
||||
void createsStatsBeansWithoutProtocolListenerOrEventFileStore() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(
|
||||
SinkMqAutoConfiguration.class,
|
||||
KafkaSinkAutoConfiguration.class,
|
||||
VehicleStatAutoConfiguration.class))
|
||||
.withAllowBeanDefinitionOverriding(true)
|
||||
.withBean("kafkaProducer", KafkaProducer.class, VehicleAnalyticsAppCompositionTest::kafkaProducer)
|
||||
.withBean(JdbcTemplate.class, () -> mock(JdbcTemplate.class))
|
||||
.withBean(ObjectMapper.class, ObjectMapper::new)
|
||||
.withPropertyValues(
|
||||
"lingniu.ingest.sink.mq.enabled=true",
|
||||
"lingniu.ingest.sink.mq.type=kafka",
|
||||
"lingniu.ingest.sink.mq.bootstrap-servers=localhost:9092",
|
||||
"lingniu.ingest.sink.mq.consumer.enabled=false",
|
||||
"lingniu.ingest.sink.kafka.enabled=true",
|
||||
"lingniu.ingest.sink.kafka.bootstrap-servers=localhost:9092",
|
||||
"lingniu.ingest.sink.kafka.consumer.enabled=false",
|
||||
"lingniu.ingest.vehicle-stat.enabled=true",
|
||||
"lingniu.ingest.vehicle-stat.jt808.enabled=true",
|
||||
"lingniu.ingest.event-history.enabled=false",
|
||||
|
||||
@@ -29,12 +29,12 @@ class VehicleAnalyticsAppDefaultsTest {
|
||||
.containsEntry(
|
||||
"lingniu.ingest.vehicle-stat.jt808.enabled",
|
||||
"${VEHICLE_STAT_JT808_MILEAGE_ENABLED:true}")
|
||||
.containsEntry("lingniu.ingest.sink.mq.consumer.enabled", "${KAFKA_CONSUMER_ENABLED:true}")
|
||||
.containsEntry("lingniu.ingest.sink.kafka.consumer.enabled", "${KAFKA_CONSUMER_ENABLED:true}")
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.vehicleStatEnvelopeConsumerProcessor.enabled",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.vehicleStatEnvelopeConsumerProcessor.enabled",
|
||||
"${VEHICLE_STAT_ENABLED:true}")
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.vehicleStatEnvelopeConsumerProcessor.group-id",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.vehicleStatEnvelopeConsumerProcessor.group-id",
|
||||
"${KAFKA_GROUP_STAT:vehicle-stat}")
|
||||
.containsEntry("management.endpoints.web.exposure.include", "health,info,metrics,prometheus");
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.lingniu.ingest.historyapp;
|
||||
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeConsumerProcessor;
|
||||
import com.lingniu.ingest.sink.mq.KafkaEnvelopeConsumerFactory;
|
||||
import com.lingniu.ingest.sink.mq.KafkaEnvelopeConsumerRunner;
|
||||
import com.lingniu.ingest.sink.mq.KafkaEnvelopeConsumerWorker;
|
||||
import com.lingniu.ingest.sink.mq.SinkMqProperties;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaEnvelopeConsumerFactory;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaEnvelopeConsumerRunner;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaEnvelopeConsumerWorker;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaSinkProperties;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
@@ -20,11 +20,11 @@ public class VehicleHistoryKafkaConsumerConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty(prefix = "lingniu.ingest.sink.mq.consumer", name = "enabled", havingValue = "true")
|
||||
@ConditionalOnProperty(prefix = "lingniu.ingest.sink.kafka.consumer", name = "enabled", havingValue = "true")
|
||||
public KafkaEnvelopeConsumerRunner vehicleHistoryKafkaEnvelopeConsumerRunner(
|
||||
@Qualifier("eventHistoryEnvelopeConsumerProcessor") EnvelopeConsumerProcessor processor,
|
||||
@Qualifier("eventHistoryRawEnvelopeConsumerProcessor") EnvelopeConsumerProcessor rawProcessor,
|
||||
SinkMqProperties props) {
|
||||
KafkaSinkProperties props) {
|
||||
List<KafkaEnvelopeConsumerWorker> workers = new KafkaEnvelopeConsumerFactory().createWorkers(
|
||||
Map.of(
|
||||
"eventHistoryGb32960EnvelopeConsumerProcessor", processor,
|
||||
|
||||
@@ -34,9 +34,8 @@ lingniu:
|
||||
server:
|
||||
enabled: false
|
||||
sink:
|
||||
mq:
|
||||
kafka:
|
||||
enabled: ${KAFKA_ENABLED:true}
|
||||
type: kafka
|
||||
bootstrap-servers: ${KAFKA_BROKERS:114.55.58.251:9092}
|
||||
topics:
|
||||
realtime: ${KAFKA_TOPIC_GB32960_EVENT:vehicle.event.gb32960.v1}
|
||||
|
||||
@@ -15,15 +15,15 @@ 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;
|
||||
import com.lingniu.ingest.sink.mq.KafkaEnvelopeDeadLetterSink;
|
||||
import com.lingniu.ingest.sink.mq.KafkaEventSink;
|
||||
import com.lingniu.ingest.sink.mq.KafkaEnvelopeConsumerRunner;
|
||||
import com.lingniu.ingest.sink.mq.SinkMqProperties;
|
||||
import com.lingniu.ingest.sink.mq.proto.ParseStatusProto;
|
||||
import com.lingniu.ingest.sink.mq.proto.RawArchiveRef;
|
||||
import com.lingniu.ingest.sink.mq.proto.RawFrameFactPayload;
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.mq.SinkMqAutoConfiguration;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaEnvelopeDeadLetterSink;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaEventSink;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaEnvelopeConsumerRunner;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaSinkProperties;
|
||||
import com.lingniu.ingest.sink.kafka.proto.ParseStatusProto;
|
||||
import com.lingniu.ingest.sink.kafka.proto.RawArchiveRef;
|
||||
import com.lingniu.ingest.sink.kafka.proto.RawFrameFactPayload;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaSinkAutoConfiguration;
|
||||
import com.lingniu.ingest.tdenginehistory.TdengineHistorySchema;
|
||||
import com.lingniu.ingest.tdenginehistory.TdengineHistoryWriter;
|
||||
import com.lingniu.ingest.tdenginehistory.TdengineRawFrameRow;
|
||||
@@ -75,8 +75,8 @@ class VehicleHistoryAppCompositionTest {
|
||||
() -> processor("event-history"))
|
||||
.withBean("eventHistoryRawEnvelopeConsumerProcessor", EnvelopeConsumerProcessor.class,
|
||||
() -> processor("event-history-raw"))
|
||||
.withBean(SinkMqProperties.class, VehicleHistoryAppCompositionTest::genericOnlyHistoryConsumerProps)
|
||||
.withPropertyValues("lingniu.ingest.sink.mq.consumer.enabled=true")
|
||||
.withBean(KafkaSinkProperties.class, VehicleHistoryAppCompositionTest::genericOnlyHistoryConsumerProps)
|
||||
.withPropertyValues("lingniu.ingest.sink.kafka.consumer.enabled=true")
|
||||
.run(context -> {
|
||||
assertThat(context).hasFailed();
|
||||
assertThat(context.getStartupFailure())
|
||||
@@ -89,7 +89,7 @@ class VehicleHistoryAppCompositionTest {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(
|
||||
TdengineHistoryAutoConfiguration.class,
|
||||
SinkMqAutoConfiguration.class,
|
||||
KafkaSinkAutoConfiguration.class,
|
||||
Gb32960AutoConfiguration.class,
|
||||
EventHistoryAutoConfiguration.class))
|
||||
.withUserConfiguration(VehicleHistoryKafkaConsumerConfiguration.class)
|
||||
@@ -101,10 +101,9 @@ class VehicleHistoryAppCompositionTest {
|
||||
"lingniu.ingest.event-history.enabled=true",
|
||||
"lingniu.ingest.gb32960.enabled=true",
|
||||
"lingniu.ingest.gb32960.server.enabled=false",
|
||||
"lingniu.ingest.sink.mq.enabled=true",
|
||||
"lingniu.ingest.sink.mq.type=kafka",
|
||||
"lingniu.ingest.sink.mq.bootstrap-servers=localhost:9092",
|
||||
"lingniu.ingest.sink.mq.consumer.enabled=false",
|
||||
"lingniu.ingest.sink.kafka.enabled=true",
|
||||
"lingniu.ingest.sink.kafka.bootstrap-servers=localhost:9092",
|
||||
"lingniu.ingest.sink.kafka.consumer.enabled=false",
|
||||
"lingniu.ingest.vehicle-state.enabled=false",
|
||||
"lingniu.ingest.vehicle-stat.enabled=false")
|
||||
.run(context -> {
|
||||
@@ -137,7 +136,7 @@ class VehicleHistoryAppCompositionTest {
|
||||
.withBean(EnvelopeDeadLetterSink.class, () -> mock(EnvelopeDeadLetterSink.class))
|
||||
.withPropertyValues(
|
||||
"lingniu.ingest.event-history.enabled=true",
|
||||
"lingniu.ingest.sink.mq.consumer.enabled=false")
|
||||
"lingniu.ingest.sink.kafka.consumer.enabled=false")
|
||||
.run(context -> {
|
||||
assertThat(context).hasSingleBean(EventHistoryEnvelopeIngestor.class);
|
||||
assertThat(context).doesNotHaveBean("eventFileStore");
|
||||
@@ -149,7 +148,7 @@ class VehicleHistoryAppCompositionTest {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(
|
||||
TdengineHistoryAutoConfiguration.class,
|
||||
SinkMqAutoConfiguration.class,
|
||||
KafkaSinkAutoConfiguration.class,
|
||||
EventHistoryAutoConfiguration.class))
|
||||
.withUserConfiguration(VehicleHistoryKafkaConsumerConfiguration.class)
|
||||
.withAllowBeanDefinitionOverriding(true)
|
||||
@@ -158,13 +157,12 @@ class VehicleHistoryAppCompositionTest {
|
||||
"lingniu.ingest.tdengine-history.enabled=true",
|
||||
"lingniu.ingest.tdengine-history.database=vehicle_history_test",
|
||||
"lingniu.ingest.event-history.enabled=true",
|
||||
"lingniu.ingest.sink.mq.enabled=true",
|
||||
"lingniu.ingest.sink.mq.type=kafka",
|
||||
"lingniu.ingest.sink.mq.bootstrap-servers=localhost:9092",
|
||||
"lingniu.ingest.sink.mq.consumer.enabled=true",
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryGb32960EnvelopeConsumerProcessor.enabled=true",
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryGb32960EnvelopeConsumerProcessor.group-id=history-gb32960",
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryGb32960EnvelopeConsumerProcessor.topics[0]=vehicle.event.gb32960.v1")
|
||||
"lingniu.ingest.sink.kafka.enabled=true",
|
||||
"lingniu.ingest.sink.kafka.bootstrap-servers=localhost:9092",
|
||||
"lingniu.ingest.sink.kafka.consumer.enabled=true",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryGb32960EnvelopeConsumerProcessor.enabled=true",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryGb32960EnvelopeConsumerProcessor.group-id=history-gb32960",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryGb32960EnvelopeConsumerProcessor.topics[0]=vehicle.event.gb32960.v1")
|
||||
.run(context -> {
|
||||
assertThat(context).hasSingleBean(EventHistoryEnvelopeIngestor.class);
|
||||
assertThat(context.getBeanNamesForType(EnvelopeConsumerProcessor.class))
|
||||
@@ -186,7 +184,7 @@ class VehicleHistoryAppCompositionTest {
|
||||
.withBean(EnvelopeDeadLetterSink.class, () -> mock(EnvelopeDeadLetterSink.class))
|
||||
.withPropertyValues(
|
||||
"lingniu.ingest.event-history.enabled=true",
|
||||
"lingniu.ingest.sink.mq.consumer.enabled=false")
|
||||
"lingniu.ingest.sink.kafka.consumer.enabled=false")
|
||||
.run(context -> {
|
||||
EventHistoryEnvelopeIngestor ingestor = context.getBean(EventHistoryEnvelopeIngestor.class);
|
||||
|
||||
@@ -211,8 +209,8 @@ class VehicleHistoryAppCompositionTest {
|
||||
ignored -> {});
|
||||
}
|
||||
|
||||
private static SinkMqProperties genericOnlyHistoryConsumerProps() {
|
||||
SinkMqProperties props = new SinkMqProperties();
|
||||
private static KafkaSinkProperties genericOnlyHistoryConsumerProps() {
|
||||
KafkaSinkProperties props = new KafkaSinkProperties();
|
||||
props.setBootstrapServers("localhost:9092");
|
||||
props.getConsumer().setEnabled(true);
|
||||
props.getConsumer().setBindings(Map.of(
|
||||
@@ -221,8 +219,8 @@ class VehicleHistoryAppCompositionTest {
|
||||
return props;
|
||||
}
|
||||
|
||||
private static SinkMqProperties.Binding binding(String groupId, String topic) {
|
||||
SinkMqProperties.Binding binding = new SinkMqProperties.Binding();
|
||||
private static KafkaSinkProperties.Binding binding(String groupId, String topic) {
|
||||
KafkaSinkProperties.Binding binding = new KafkaSinkProperties.Binding();
|
||||
binding.setGroupId(groupId);
|
||||
binding.setTopics(List.of(topic));
|
||||
return binding;
|
||||
|
||||
@@ -44,65 +44,65 @@ class VehicleHistoryAppDefaultsTest {
|
||||
.containsEntry("lingniu.ingest.event-history.enabled", true)
|
||||
.containsEntry("lingniu.ingest.vehicle-state.enabled", false)
|
||||
.containsEntry("lingniu.ingest.vehicle-stat.enabled", false)
|
||||
.containsEntry("lingniu.ingest.sink.mq.consumer.enabled", "${KAFKA_CONSUMER_ENABLED:true}")
|
||||
.containsEntry("lingniu.ingest.sink.mq.consumer.max-poll-records", "${KAFKA_CONSUMER_MAX_POLL_RECORDS:2000}")
|
||||
.containsEntry("lingniu.ingest.sink.mq.consumer.concurrency", "${KAFKA_CONSUMER_CONCURRENCY:3}")
|
||||
.containsEntry("lingniu.ingest.sink.kafka.consumer.enabled", "${KAFKA_CONSUMER_ENABLED:true}")
|
||||
.containsEntry("lingniu.ingest.sink.kafka.consumer.max-poll-records", "${KAFKA_CONSUMER_MAX_POLL_RECORDS:2000}")
|
||||
.containsEntry("lingniu.ingest.sink.kafka.consumer.concurrency", "${KAFKA_CONSUMER_CONCURRENCY:3}")
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.max-poll-interval-millis",
|
||||
"lingniu.ingest.sink.kafka.consumer.max-poll-interval-millis",
|
||||
"${KAFKA_CONSUMER_MAX_POLL_INTERVAL_MS:1800000}")
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryGb32960EnvelopeConsumerProcessor.enabled",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryGb32960EnvelopeConsumerProcessor.enabled",
|
||||
true)
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryGb32960EnvelopeConsumerProcessor.group-id",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryGb32960EnvelopeConsumerProcessor.group-id",
|
||||
"${KAFKA_GROUP_HISTORY_GB32960_EVENT:${KAFKA_GROUP_HISTORY:vehicle-history}-gb32960-event}")
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryGb32960EnvelopeConsumerProcessor.topics[0]",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryGb32960EnvelopeConsumerProcessor.topics[0]",
|
||||
"${KAFKA_TOPIC_GB32960_EVENT:vehicle.event.gb32960.v1}")
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryJt808EnvelopeConsumerProcessor.enabled",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryJt808EnvelopeConsumerProcessor.enabled",
|
||||
true)
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryJt808EnvelopeConsumerProcessor.group-id",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryJt808EnvelopeConsumerProcessor.group-id",
|
||||
"${KAFKA_GROUP_HISTORY_JT808_EVENT:${KAFKA_GROUP_HISTORY:vehicle-history}-jt808-event}")
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryJt808EnvelopeConsumerProcessor.topics[0]",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryJt808EnvelopeConsumerProcessor.topics[0]",
|
||||
"${KAFKA_TOPIC_JT808_EVENT:vehicle.event.jt808.v1}")
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryYutongMqttEnvelopeConsumerProcessor.enabled",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryYutongMqttEnvelopeConsumerProcessor.enabled",
|
||||
true)
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryYutongMqttEnvelopeConsumerProcessor.group-id",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryYutongMqttEnvelopeConsumerProcessor.group-id",
|
||||
"${KAFKA_GROUP_HISTORY_YUTONG_MQTT_EVENT:${KAFKA_GROUP_HISTORY:vehicle-history}-yutong-mqtt-event}")
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryYutongMqttEnvelopeConsumerProcessor.topics[0]",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryYutongMqttEnvelopeConsumerProcessor.topics[0]",
|
||||
"${KAFKA_TOPIC_YUTONG_MQTT_EVENT:vehicle.event.mqtt-yutong.v1}")
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryGb32960RawEnvelopeConsumerProcessor.enabled",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryGb32960RawEnvelopeConsumerProcessor.enabled",
|
||||
true)
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryGb32960RawEnvelopeConsumerProcessor.group-id",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryGb32960RawEnvelopeConsumerProcessor.group-id",
|
||||
"${KAFKA_GROUP_HISTORY_GB32960_RAW:${KAFKA_GROUP_HISTORY:vehicle-history}-gb32960-raw}")
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryGb32960RawEnvelopeConsumerProcessor.topics[0]",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryGb32960RawEnvelopeConsumerProcessor.topics[0]",
|
||||
"${KAFKA_TOPIC_GB32960_RAW:vehicle.raw.gb32960.v1}")
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryJt808RawEnvelopeConsumerProcessor.enabled",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryJt808RawEnvelopeConsumerProcessor.enabled",
|
||||
true)
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryJt808RawEnvelopeConsumerProcessor.group-id",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryJt808RawEnvelopeConsumerProcessor.group-id",
|
||||
"${KAFKA_GROUP_HISTORY_JT808_RAW:${KAFKA_GROUP_HISTORY:vehicle-history}-jt808-raw}")
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryJt808RawEnvelopeConsumerProcessor.topics[0]",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryJt808RawEnvelopeConsumerProcessor.topics[0]",
|
||||
"${KAFKA_TOPIC_JT808_RAW:vehicle.raw.jt808.v1}")
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryYutongMqttRawEnvelopeConsumerProcessor.enabled",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryYutongMqttRawEnvelopeConsumerProcessor.enabled",
|
||||
true)
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryYutongMqttRawEnvelopeConsumerProcessor.group-id",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryYutongMqttRawEnvelopeConsumerProcessor.group-id",
|
||||
"${KAFKA_GROUP_HISTORY_YUTONG_MQTT_RAW:${KAFKA_GROUP_HISTORY:vehicle-history}-yutong-mqtt-raw}")
|
||||
.containsEntry(
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.eventHistoryYutongMqttRawEnvelopeConsumerProcessor.topics[0]",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryYutongMqttRawEnvelopeConsumerProcessor.topics[0]",
|
||||
"${KAFKA_TOPIC_YUTONG_MQTT_RAW:vehicle.raw.mqtt-yutong.v1}")
|
||||
.containsEntry("management.endpoints.web.exposure.include", "health,info,metrics,prometheus");
|
||||
|
||||
|
||||
@@ -53,20 +53,16 @@ lingniu:
|
||||
rate-limit:
|
||||
per-vin-qps: 50
|
||||
identity:
|
||||
store: ${VEHICLE_IDENTITY_STORE:file}
|
||||
file:
|
||||
path: ${VEHICLE_IDENTITY_FILE:./data/vehicle-identity.jsonl}
|
||||
store: ${VEHICLE_IDENTITY_STORE:mysql}
|
||||
mysql:
|
||||
table: ${VEHICLE_IDENTITY_MYSQL_TABLE:vehicle_identity_binding}
|
||||
jdbc-url: ${VEHICLE_IDENTITY_MYSQL_JDBC_URL:}
|
||||
username: ${VEHICLE_IDENTITY_MYSQL_USERNAME:}
|
||||
jdbc-url: ${VEHICLE_IDENTITY_MYSQL_JDBC_URL:jdbc:mysql://127.0.0.1:3306/lingniu_vehicle?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai}
|
||||
username: ${VEHICLE_IDENTITY_MYSQL_USERNAME:root}
|
||||
password: ${VEHICLE_IDENTITY_MYSQL_PASSWORD:}
|
||||
driver-class-name: ${VEHICLE_IDENTITY_MYSQL_DRIVER_CLASS_NAME:com.mysql.cj.jdbc.Driver}
|
||||
refresh-interval: ${VEHICLE_IDENTITY_MYSQL_REFRESH_INTERVAL:60s}
|
||||
table-name: ${VEHICLE_IDENTITY_MYSQL_TABLE:vehicle_identity_bindings}
|
||||
initialize-schema: ${VEHICLE_IDENTITY_MYSQL_INITIALIZE_SCHEMA:true}
|
||||
sink:
|
||||
mq:
|
||||
kafka:
|
||||
enabled: ${KAFKA_ENABLED:true}
|
||||
type: kafka
|
||||
bootstrap-servers: ${KAFKA_BROKERS:114.55.58.251:9092}
|
||||
compression-type: zstd
|
||||
linger-ms: 20
|
||||
|
||||
@@ -9,9 +9,9 @@ import com.lingniu.ingest.inbound.xinda.config.XindaPushAutoConfiguration;
|
||||
import com.lingniu.ingest.sink.archive.ArchiveStore;
|
||||
import com.lingniu.ingest.sink.archive.RawArchiveEventSink;
|
||||
import com.lingniu.ingest.sink.archive.config.SinkArchiveAutoConfiguration;
|
||||
import com.lingniu.ingest.sink.mq.KafkaEnvelopeDeadLetterSink;
|
||||
import com.lingniu.ingest.sink.mq.KafkaEventSink;
|
||||
import com.lingniu.ingest.sink.mq.SinkMqAutoConfiguration;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaEnvelopeDeadLetterSink;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaEventSink;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaSinkAutoConfiguration;
|
||||
import org.apache.kafka.clients.producer.KafkaProducer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
@@ -26,7 +26,7 @@ class XindaPushAppCompositionTest {
|
||||
.withConfiguration(AutoConfigurations.of(
|
||||
IngestCoreAutoConfiguration.class,
|
||||
VehicleIdentityAutoConfiguration.class,
|
||||
SinkMqAutoConfiguration.class,
|
||||
KafkaSinkAutoConfiguration.class,
|
||||
SinkArchiveAutoConfiguration.class,
|
||||
XindaPushAutoConfiguration.class))
|
||||
.withAllowBeanDefinitionOverriding(true)
|
||||
@@ -37,10 +37,11 @@ class XindaPushAppCompositionTest {
|
||||
"lingniu.ingest.xinda-push.port=10100",
|
||||
"lingniu.ingest.xinda-push.username=test",
|
||||
"lingniu.ingest.xinda-push.password=test",
|
||||
"lingniu.ingest.sink.mq.enabled=true",
|
||||
"lingniu.ingest.sink.mq.type=kafka",
|
||||
"lingniu.ingest.sink.mq.bootstrap-servers=localhost:9092",
|
||||
"lingniu.ingest.sink.mq.consumer.enabled=false",
|
||||
"lingniu.ingest.identity.store=mysql",
|
||||
"lingniu.ingest.identity.mysql.initialize-schema=false",
|
||||
"lingniu.ingest.sink.kafka.enabled=true",
|
||||
"lingniu.ingest.sink.kafka.bootstrap-servers=localhost:9092",
|
||||
"lingniu.ingest.sink.kafka.consumer.enabled=false",
|
||||
"lingniu.ingest.sink.archive.enabled=true",
|
||||
"lingniu.ingest.sink.archive.path=target/test-archive-xinda",
|
||||
"lingniu.ingest.event-file-store.enabled=false",
|
||||
|
||||
@@ -26,13 +26,14 @@ class XindaPushAppDefaultsTest {
|
||||
.containsEntry("lingniu.ingest.xinda-push.port", "${XINDA_PUSH_PORT:10100}")
|
||||
.containsEntry("lingniu.ingest.xinda-push.username", "${XINDA_PUSH_USERNAME:}")
|
||||
.containsEntry("lingniu.ingest.xinda-push.subscribe-msg-ids[0]", "${XINDA_PUSH_MSG_ID_LOCATION:0200}")
|
||||
.containsEntry("lingniu.ingest.sink.mq.enabled", "${KAFKA_ENABLED:true}")
|
||||
.containsEntry("lingniu.ingest.sink.mq.consumer.enabled", false)
|
||||
.containsEntry("lingniu.ingest.sink.mq.topics.realtime", "${KAFKA_TOPIC_XINDA_PUSH_EVENT:vehicle.event.xinda-push.v1}")
|
||||
.containsEntry("lingniu.ingest.sink.mq.topics.raw-archive", "${KAFKA_TOPIC_XINDA_PUSH_RAW:vehicle.raw.xinda-push.v1}")
|
||||
.containsEntry("lingniu.ingest.sink.mq.topics.dlq", "${KAFKA_TOPIC_XINDA_PUSH_DLQ:vehicle.dlq.xinda-push.v1}")
|
||||
.containsEntry("lingniu.ingest.identity.store", "${VEHICLE_IDENTITY_STORE:file}")
|
||||
.containsEntry("lingniu.ingest.identity.mysql.table", "${VEHICLE_IDENTITY_MYSQL_TABLE:vehicle_identity_binding}")
|
||||
.containsEntry("lingniu.ingest.sink.kafka.enabled", "${KAFKA_ENABLED:true}")
|
||||
.containsEntry("lingniu.ingest.sink.kafka.consumer.enabled", false)
|
||||
.containsEntry("lingniu.ingest.sink.kafka.topics.realtime", "${KAFKA_TOPIC_XINDA_PUSH_EVENT:vehicle.event.xinda-push.v1}")
|
||||
.containsEntry("lingniu.ingest.sink.kafka.topics.raw-archive", "${KAFKA_TOPIC_XINDA_PUSH_RAW:vehicle.raw.xinda-push.v1}")
|
||||
.containsEntry("lingniu.ingest.sink.kafka.topics.dlq", "${KAFKA_TOPIC_XINDA_PUSH_DLQ:vehicle.dlq.xinda-push.v1}")
|
||||
.containsEntry("lingniu.ingest.identity.store", "${VEHICLE_IDENTITY_STORE:mysql}")
|
||||
.containsEntry("lingniu.ingest.identity.mysql.table-name",
|
||||
"${VEHICLE_IDENTITY_MYSQL_TABLE:vehicle_identity_bindings}")
|
||||
.containsEntry("lingniu.ingest.sink.archive.enabled", "${SINK_ARCHIVE_ENABLED:true}")
|
||||
.containsEntry("lingniu.ingest.event-file-store.enabled", false)
|
||||
.containsEntry("lingniu.ingest.event-history.enabled", false)
|
||||
|
||||
@@ -69,9 +69,8 @@ lingniu:
|
||||
table-name: ${VEHICLE_IDENTITY_MYSQL_TABLE:vehicle_identity_bindings}
|
||||
initialize-schema: ${VEHICLE_IDENTITY_MYSQL_INITIALIZE_SCHEMA:true}
|
||||
sink:
|
||||
mq:
|
||||
kafka:
|
||||
enabled: ${KAFKA_ENABLED:true}
|
||||
type: kafka
|
||||
bootstrap-servers: ${KAFKA_BROKERS:114.55.58.251:9092}
|
||||
compression-type: zstd
|
||||
linger-ms: 20
|
||||
|
||||
@@ -10,9 +10,9 @@ import com.lingniu.ingest.inbound.mqtt.profile.MqttProfileRegistry;
|
||||
import com.lingniu.ingest.sink.archive.ArchiveStore;
|
||||
import com.lingniu.ingest.sink.archive.RawArchiveEventSink;
|
||||
import com.lingniu.ingest.sink.archive.config.SinkArchiveAutoConfiguration;
|
||||
import com.lingniu.ingest.sink.mq.KafkaEnvelopeDeadLetterSink;
|
||||
import com.lingniu.ingest.sink.mq.KafkaEventSink;
|
||||
import com.lingniu.ingest.sink.mq.SinkMqAutoConfiguration;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaEnvelopeDeadLetterSink;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaEventSink;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaSinkAutoConfiguration;
|
||||
import org.apache.kafka.clients.producer.KafkaProducer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -31,7 +31,7 @@ class YutongMqttAppCompositionTest {
|
||||
.withConfiguration(AutoConfigurations.of(
|
||||
IngestCoreAutoConfiguration.class,
|
||||
VehicleIdentityAutoConfiguration.class,
|
||||
SinkMqAutoConfiguration.class,
|
||||
KafkaSinkAutoConfiguration.class,
|
||||
SinkArchiveAutoConfiguration.class,
|
||||
MqttInboundAutoConfiguration.class))
|
||||
.withAllowBeanDefinitionOverriding(true)
|
||||
@@ -45,10 +45,9 @@ class YutongMqttAppCompositionTest {
|
||||
"lingniu.ingest.mqtt.endpoints[0].profile=yutong",
|
||||
"lingniu.ingest.identity.store=mysql",
|
||||
"lingniu.ingest.identity.mysql.initialize-schema=false",
|
||||
"lingniu.ingest.sink.mq.enabled=true",
|
||||
"lingniu.ingest.sink.mq.type=kafka",
|
||||
"lingniu.ingest.sink.mq.bootstrap-servers=localhost:9092",
|
||||
"lingniu.ingest.sink.mq.consumer.enabled=false",
|
||||
"lingniu.ingest.sink.kafka.enabled=true",
|
||||
"lingniu.ingest.sink.kafka.bootstrap-servers=localhost:9092",
|
||||
"lingniu.ingest.sink.kafka.consumer.enabled=false",
|
||||
"lingniu.ingest.sink.archive.enabled=true",
|
||||
"lingniu.ingest.sink.archive.path=target/test-archive-yutong",
|
||||
"lingniu.ingest.event-history.enabled=false");
|
||||
|
||||
@@ -28,11 +28,11 @@ class YutongMqttAppDefaultsTest {
|
||||
.containsEntry("lingniu.ingest.mqtt.endpoints[0].uri", "${YUTONG_MQTT_URI:}")
|
||||
.containsEntry("lingniu.ingest.mqtt.endpoints[0].topic", "${YUTONG_MQTT_TOPIC:#}")
|
||||
.containsEntry("lingniu.ingest.mqtt.endpoints[0].profile", "yutong")
|
||||
.containsEntry("lingniu.ingest.sink.mq.enabled", "${KAFKA_ENABLED:true}")
|
||||
.containsEntry("lingniu.ingest.sink.mq.consumer.enabled", false)
|
||||
.containsEntry("lingniu.ingest.sink.mq.topics.realtime", "${KAFKA_TOPIC_YUTONG_MQTT_EVENT:vehicle.event.mqtt-yutong.v1}")
|
||||
.containsEntry("lingniu.ingest.sink.mq.topics.raw-archive", "${KAFKA_TOPIC_YUTONG_MQTT_RAW:vehicle.raw.mqtt-yutong.v1}")
|
||||
.containsEntry("lingniu.ingest.sink.mq.topics.dlq", "${KAFKA_TOPIC_YUTONG_MQTT_DLQ:vehicle.dlq.mqtt-yutong.v1}")
|
||||
.containsEntry("lingniu.ingest.sink.kafka.enabled", "${KAFKA_ENABLED:true}")
|
||||
.containsEntry("lingniu.ingest.sink.kafka.consumer.enabled", false)
|
||||
.containsEntry("lingniu.ingest.sink.kafka.topics.realtime", "${KAFKA_TOPIC_YUTONG_MQTT_EVENT:vehicle.event.mqtt-yutong.v1}")
|
||||
.containsEntry("lingniu.ingest.sink.kafka.topics.raw-archive", "${KAFKA_TOPIC_YUTONG_MQTT_RAW:vehicle.raw.mqtt-yutong.v1}")
|
||||
.containsEntry("lingniu.ingest.sink.kafka.topics.dlq", "${KAFKA_TOPIC_YUTONG_MQTT_DLQ:vehicle.dlq.mqtt-yutong.v1}")
|
||||
.containsEntry("lingniu.ingest.identity.store", "${VEHICLE_IDENTITY_STORE:mysql}")
|
||||
.containsEntry("lingniu.ingest.identity.mysql.table-name",
|
||||
"${VEHICLE_IDENTITY_MYSQL_TABLE:vehicle_identity_bindings}")
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.lingniu.ingest.api.consumer.EnvelopeBatchIngestor;
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeIngestResult;
|
||||
import com.lingniu.ingest.api.history.EventFileRecord;
|
||||
import com.lingniu.ingest.api.history.EventFileStore;
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.tdenginehistory.TdengineEnvelopeRows;
|
||||
import com.lingniu.ingest.tdenginehistory.TdengineHistoryWriter;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@@ -5,8 +5,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.lingniu.ingest.api.ProtocolId;
|
||||
import com.lingniu.ingest.api.event.RawArchiveKeys;
|
||||
import com.lingniu.ingest.api.history.EventFileRecord;
|
||||
import com.lingniu.ingest.sink.mq.proto.RawArchiveRef;
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.proto.RawArchiveRef;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import com.google.protobuf.util.JsonFormat;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import com.lingniu.ingest.eventhistory.TelemetryFieldHistoryController;
|
||||
import com.lingniu.ingest.eventhistory.TelemetryEnvelopeRecordMapper;
|
||||
import com.lingniu.ingest.protocol.gb32960.codec.Gb32960MessageDecoder;
|
||||
import com.lingniu.ingest.protocol.gb32960.config.Gb32960AutoConfiguration;
|
||||
import com.lingniu.ingest.sink.mq.SinkMqAutoConfiguration;
|
||||
import com.lingniu.ingest.sink.kafka.KafkaSinkAutoConfiguration;
|
||||
import com.lingniu.ingest.tdenginehistory.config.TdengineHistoryAutoConfiguration;
|
||||
import com.lingniu.ingest.tdenginehistory.TdengineHistoryReader;
|
||||
import com.lingniu.ingest.tdenginehistory.TdengineHistoryWriter;
|
||||
@@ -41,12 +41,12 @@ import java.nio.file.Path;
|
||||
* </ul>
|
||||
*
|
||||
* <p>当前生产 history app 以 TDengine 为准;Kafka consumer 是否启动还取决于
|
||||
* {@code lingniu.ingest.sink.mq.consumer.enabled=true}。
|
||||
* {@code lingniu.ingest.sink.kafka.consumer.enabled=true}。
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@AutoConfigureAfter({
|
||||
Gb32960AutoConfiguration.class,
|
||||
SinkMqAutoConfiguration.class,
|
||||
KafkaSinkAutoConfiguration.class,
|
||||
TdengineHistoryAutoConfiguration.class
|
||||
})
|
||||
@ConditionalOnProperty(prefix = "lingniu.ingest.event-history", name = "enabled", havingValue = "true")
|
||||
@@ -82,7 +82,7 @@ public class EventHistoryAutoConfiguration {
|
||||
@ConditionalOnMissingBean(name = "eventHistoryEnvelopeConsumerProcessor")
|
||||
public EnvelopeConsumerProcessor eventHistoryEnvelopeConsumerProcessor(EventHistoryEnvelopeIngestor ingestor,
|
||||
EnvelopeDeadLetterSink deadLetterSink) {
|
||||
// 只注册 processor;真正拉 Kafka 的 runner 在 sink-mq 模块按 consumer.enabled 决定是否创建。
|
||||
// 只注册 processor;真正拉 Kafka 的 runner 按 consumer.enabled 决定是否创建。
|
||||
return new EnvelopeConsumerProcessor("event-history", ingestor, deadLetterSink);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,13 +9,13 @@ import com.lingniu.ingest.api.event.RawArchiveKeys;
|
||||
import com.lingniu.ingest.api.history.EventFileQuery;
|
||||
import com.lingniu.ingest.api.history.EventFileRecord;
|
||||
import com.lingniu.ingest.api.history.EventFileStore;
|
||||
import com.lingniu.ingest.sink.mq.proto.RawArchiveRef;
|
||||
import com.lingniu.ingest.sink.mq.proto.RawFrameFactPayload;
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetrySnapshot;
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.mq.proto.LocationPayload;
|
||||
import com.lingniu.ingest.sink.mq.proto.ParseStatusProto;
|
||||
import com.lingniu.ingest.sink.kafka.proto.RawArchiveRef;
|
||||
import com.lingniu.ingest.sink.kafka.proto.RawFrameFactPayload;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetrySnapshot;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.proto.LocationPayload;
|
||||
import com.lingniu.ingest.sink.kafka.proto.ParseStatusProto;
|
||||
import com.lingniu.ingest.tdenginehistory.TdengineHistoryWriter;
|
||||
import com.lingniu.ingest.tdenginehistory.TdengineLocationRow;
|
||||
import com.lingniu.ingest.tdenginehistory.TdengineRawFrameRow;
|
||||
|
||||
@@ -2,10 +2,10 @@ package com.lingniu.ingest.eventhistory;
|
||||
|
||||
import com.lingniu.ingest.api.ProtocolId;
|
||||
import com.lingniu.ingest.api.history.EventFileRecord;
|
||||
import com.lingniu.ingest.sink.mq.proto.RawArchiveRef;
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetrySnapshot;
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.proto.RawArchiveRef;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetrySnapshot;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ class EventHistoryAutoConfigurationTest {
|
||||
contextRunner
|
||||
.withPropertyValues(
|
||||
"lingniu.ingest.event-history.enabled=true",
|
||||
"lingniu.ingest.sink.mq.consumer.enabled=true")
|
||||
"lingniu.ingest.sink.kafka.consumer.enabled=true")
|
||||
.run(context -> {
|
||||
assertThat(context).hasSingleBean(TelemetryEnvelopeRecordMapper.class);
|
||||
assertThat(context).hasSingleBean(EventHistoryEnvelopeIngestor.class);
|
||||
|
||||
@@ -22,7 +22,7 @@ class EventHistoryPomBoundaryTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void kafkaClientsIsOwnedBySinkMqModule() throws Exception {
|
||||
void kafkaClientsIsOwnedByKafkaSinkModule() throws Exception {
|
||||
for (Path pom : servicePoms()) {
|
||||
assertThat(directDependencies(readPom(pom)))
|
||||
.as(pom.toString())
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.lingniu.ingest.vehiclestat;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeIngestResult;
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeIngestor;
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.vehiclestat.jt808.Jt808MileageStreamProcessor;
|
||||
|
||||
public final class VehicleStatEnvelopeIngestor implements EnvelopeIngestor {
|
||||
|
||||
@@ -78,7 +78,7 @@ public class VehicleStatAutoConfiguration {
|
||||
@ConditionalOnMissingBean(name = "vehicleStatEnvelopeConsumerProcessor")
|
||||
public EnvelopeConsumerProcessor vehicleStatEnvelopeConsumerProcessor(VehicleStatEnvelopeIngestor ingestor,
|
||||
EnvelopeDeadLetterSink deadLetterSink) {
|
||||
// Bean 名必须和 sink-mq 默认 binding 对齐,KafkaEnvelopeConsumerFactory 才能自动创建 worker。
|
||||
// Bean 名必须和 Kafka 默认 binding 对齐,KafkaEnvelopeConsumerFactory 才能自动创建 worker。
|
||||
return new EnvelopeConsumerProcessor("vehicle-stat", ingestor, deadLetterSink);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.lingniu.ingest.vehiclestat.jt808;
|
||||
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.lingniu.ingest.vehiclestat.jt808;
|
||||
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.vehiclestat.VehicleStatRepository;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
@@ -2,10 +2,10 @@ package com.lingniu.ingest.vehiclestat;
|
||||
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeIngestResult;
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeIngestor;
|
||||
import com.lingniu.ingest.sink.mq.proto.RawArchiveRef;
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetrySnapshot;
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.proto.RawArchiveRef;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetrySnapshot;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.vehiclestat.jt808.Jt808MileageStreamProcessor;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.lingniu.ingest.vehiclestat.jt808;
|
||||
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetrySnapshot;
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetrySnapshot;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.lingniu.ingest.vehiclestat.jt808;
|
||||
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetrySnapshot;
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetrySnapshot;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.vehiclestat.DailyMileageStrategy;
|
||||
import com.lingniu.ingest.vehiclestat.VehicleDailyStatResult;
|
||||
import com.lingniu.ingest.vehiclestat.VehicleStatRepository;
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.lingniu.ingest.vehiclestate;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeIngestResult;
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeIngestor;
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
|
||||
public final class VehicleStateEnvelopeIngestor implements EnvelopeIngestor {
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.lingniu.ingest.vehiclestate;
|
||||
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -45,7 +45,7 @@ public class VehicleStateAutoConfiguration {
|
||||
@ConditionalOnMissingBean(name = "vehicleStateEnvelopeConsumerProcessor")
|
||||
public EnvelopeConsumerProcessor vehicleStateEnvelopeConsumerProcessor(VehicleStateEnvelopeIngestor ingestor,
|
||||
EnvelopeDeadLetterSink deadLetterSink) {
|
||||
// Bean 名必须和 sink-mq 默认 binding 对齐,KafkaEnvelopeConsumerFactory 才能自动创建 worker。
|
||||
// Bean 名必须和 Kafka 默认 binding 对齐,KafkaEnvelopeConsumerFactory 才能自动创建 worker。
|
||||
return new EnvelopeConsumerProcessor("vehicle-state", ingestor, deadLetterSink);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@ package com.lingniu.ingest.vehiclestate;
|
||||
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeIngestResult;
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeIngestor;
|
||||
import com.lingniu.ingest.sink.mq.proto.RawArchiveRef;
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetrySnapshot;
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.proto.RawArchiveRef;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetrySnapshot;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.lingniu.ingest.vehiclestate;
|
||||
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetrySnapshot;
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetrySnapshot;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import com.lingniu.ingest.api.event.AlarmPayload;
|
||||
import com.lingniu.ingest.api.event.LocationPayload;
|
||||
@@ -10,10 +10,10 @@ import com.lingniu.ingest.api.event.VehicleEvent;
|
||||
import com.lingniu.ingest.api.event.VehicleEventTelemetrySnapshotMapper;
|
||||
import com.lingniu.ingest.facts.FactIds;
|
||||
import com.lingniu.ingest.facts.VehicleKey;
|
||||
import com.lingniu.ingest.sink.mq.proto.ParseStatusProto;
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetrySnapshot.Builder;
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.proto.ParseStatusProto;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetrySnapshot.Builder;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@@ -53,23 +53,23 @@ public final class EnvelopeMapper {
|
||||
case VehicleEvent.Location l -> b.setLocation(buildLocation(l.payload()));
|
||||
case VehicleEvent.Alarm a -> b.setAlarm(buildAlarm(a.payload()));
|
||||
case VehicleEvent.Login lg -> b.setLogin(
|
||||
com.lingniu.ingest.sink.mq.proto.LoginPayload.newBuilder()
|
||||
com.lingniu.ingest.sink.kafka.proto.LoginPayload.newBuilder()
|
||||
.setIccid(nullToEmpty(lg.iccid()))
|
||||
.setProtocolVersion(nullToEmpty(lg.protocolVersion()))
|
||||
.build());
|
||||
case VehicleEvent.Logout ignored -> b.setLogout(
|
||||
com.lingniu.ingest.sink.mq.proto.LogoutPayload.getDefaultInstance());
|
||||
com.lingniu.ingest.sink.kafka.proto.LogoutPayload.getDefaultInstance());
|
||||
case VehicleEvent.Heartbeat ignored -> b.setHeartbeat(
|
||||
com.lingniu.ingest.sink.mq.proto.HeartbeatPayload.getDefaultInstance());
|
||||
com.lingniu.ingest.sink.kafka.proto.HeartbeatPayload.getDefaultInstance());
|
||||
case VehicleEvent.MediaMeta m -> b.setMediaMeta(
|
||||
com.lingniu.ingest.sink.mq.proto.MediaMetaPayload.newBuilder()
|
||||
com.lingniu.ingest.sink.kafka.proto.MediaMetaPayload.newBuilder()
|
||||
.setMediaId(nullToEmpty(m.mediaId()))
|
||||
.setMediaType(nullToEmpty(m.mediaType()))
|
||||
.setSizeBytes(m.sizeBytes())
|
||||
.setArchiveRef(nullToEmpty(m.archiveRef()))
|
||||
.build());
|
||||
case VehicleEvent.Passthrough p -> b.setPassthrough(
|
||||
com.lingniu.ingest.sink.mq.proto.PassthroughPayload.newBuilder()
|
||||
com.lingniu.ingest.sink.kafka.proto.PassthroughPayload.newBuilder()
|
||||
.setPassthroughType(p.passthroughType())
|
||||
.setData(com.google.protobuf.ByteString.copyFrom(
|
||||
p.data() == null ? new byte[0] : p.data()))
|
||||
@@ -88,13 +88,13 @@ public final class EnvelopeMapper {
|
||||
b.putMetadata(RawArchiveKeys.META_KEY, key);
|
||||
b.putMetadata(RawArchiveKeys.META_URI, uri);
|
||||
b.putMetadata(RawArchiveKeys.META_EVENT_ID, ra.eventId());
|
||||
b.setRawArchive(com.lingniu.ingest.sink.mq.proto.RawArchiveRef.newBuilder()
|
||||
b.setRawArchive(com.lingniu.ingest.sink.kafka.proto.RawArchiveRef.newBuilder()
|
||||
.setUri(uri)
|
||||
.setChecksum(checksum)
|
||||
.setSizeBytes(size)
|
||||
.setParsedJson(nullToEmpty(ra.parsedJson()))
|
||||
.build());
|
||||
b.setRawFrameFact(com.lingniu.ingest.sink.mq.proto.RawFrameFactPayload.newBuilder()
|
||||
b.setRawFrameFact(com.lingniu.ingest.sink.kafka.proto.RawFrameFactPayload.newBuilder()
|
||||
.setFrameId(frameId)
|
||||
.setVehicleKey(vehicleKey)
|
||||
.setVin(nullToEmpty(ra.vin()))
|
||||
@@ -114,8 +114,8 @@ public final class EnvelopeMapper {
|
||||
return b.build();
|
||||
}
|
||||
|
||||
private static com.lingniu.ingest.sink.mq.proto.TelemetrySnapshot buildTelemetrySnapshot(TelemetrySnapshot snapshot) {
|
||||
Builder b = com.lingniu.ingest.sink.mq.proto.TelemetrySnapshot.newBuilder()
|
||||
private static com.lingniu.ingest.sink.kafka.proto.TelemetrySnapshot buildTelemetrySnapshot(TelemetrySnapshot snapshot) {
|
||||
Builder b = com.lingniu.ingest.sink.kafka.proto.TelemetrySnapshot.newBuilder()
|
||||
.setEventType(snapshot.eventType())
|
||||
.setRawArchiveUri(snapshot.rawArchiveUri());
|
||||
for (TelemetryFieldValue field : snapshot.fields()) {
|
||||
@@ -131,8 +131,8 @@ public final class EnvelopeMapper {
|
||||
return b.build();
|
||||
}
|
||||
|
||||
private static com.lingniu.ingest.sink.mq.proto.RealtimePayload buildRealtime(RealtimePayload p) {
|
||||
var b = com.lingniu.ingest.sink.mq.proto.RealtimePayload.newBuilder();
|
||||
private static com.lingniu.ingest.sink.kafka.proto.RealtimePayload buildRealtime(RealtimePayload p) {
|
||||
var b = com.lingniu.ingest.sink.kafka.proto.RealtimePayload.newBuilder();
|
||||
if (p.speedKmh() != null) b.setSpeedKmh(p.speedKmh());
|
||||
if (p.totalMileageKm() != null) b.setTotalMileageKm(p.totalMileageKm());
|
||||
if (p.batterySoc() != null) b.setBatterySoc(p.batterySoc());
|
||||
@@ -159,8 +159,8 @@ public final class EnvelopeMapper {
|
||||
return b.build();
|
||||
}
|
||||
|
||||
private static com.lingniu.ingest.sink.mq.proto.LocationPayload buildLocation(LocationPayload p) {
|
||||
return com.lingniu.ingest.sink.mq.proto.LocationPayload.newBuilder()
|
||||
private static com.lingniu.ingest.sink.kafka.proto.LocationPayload buildLocation(LocationPayload p) {
|
||||
return com.lingniu.ingest.sink.kafka.proto.LocationPayload.newBuilder()
|
||||
.setLongitude(p.longitude())
|
||||
.setLatitude(p.latitude())
|
||||
.setAltitudeM(p.altitudeM())
|
||||
@@ -171,8 +171,8 @@ public final class EnvelopeMapper {
|
||||
.build();
|
||||
}
|
||||
|
||||
private static com.lingniu.ingest.sink.mq.proto.AlarmPayload buildAlarm(AlarmPayload p) {
|
||||
var b = com.lingniu.ingest.sink.mq.proto.AlarmPayload.newBuilder()
|
||||
private static com.lingniu.ingest.sink.kafka.proto.AlarmPayload buildAlarm(AlarmPayload p) {
|
||||
var b = com.lingniu.ingest.sink.kafka.proto.AlarmPayload.newBuilder()
|
||||
.setLevel(p.level().name())
|
||||
.setAlarmTypeCode(p.alarmTypeCode())
|
||||
.setAlarmTypeName(nullToEmpty(p.alarmTypeName()));
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeConsumerProcessor;
|
||||
import org.apache.kafka.clients.consumer.ConsumerConfig;
|
||||
@@ -28,15 +28,15 @@ public final class KafkaEnvelopeConsumerFactory {
|
||||
}
|
||||
|
||||
public List<KafkaEnvelopeConsumerWorker> createWorkers(Map<String, EnvelopeConsumerProcessor> processors,
|
||||
SinkMqProperties props) {
|
||||
Map<String, SinkMqProperties.Binding> bindings = effectiveBindings(props);
|
||||
KafkaSinkProperties props) {
|
||||
Map<String, KafkaSinkProperties.Binding> bindings = effectiveBindings(props);
|
||||
List<KafkaEnvelopeConsumerWorker> workers = new ArrayList<>();
|
||||
for (Map.Entry<String, SinkMqProperties.Binding> entry : bindings.entrySet()) {
|
||||
for (Map.Entry<String, KafkaSinkProperties.Binding> entry : bindings.entrySet()) {
|
||||
String processorBeanName = entry.getKey();
|
||||
// binding 的 key 必须和 Spring Bean 名一致;这样配置只声明 topic/group,
|
||||
// 实际处理逻辑仍由各业务模块自己的 EnvelopeConsumerProcessor 承接。
|
||||
EnvelopeConsumerProcessor processor = processors.get(processorBeanName);
|
||||
SinkMqProperties.Binding binding = entry.getValue();
|
||||
KafkaSinkProperties.Binding binding = entry.getValue();
|
||||
if (processor == null || binding == null || !binding.isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
@@ -57,15 +57,15 @@ public final class KafkaEnvelopeConsumerFactory {
|
||||
return workers;
|
||||
}
|
||||
|
||||
private Map<String, SinkMqProperties.Binding> effectiveBindings(SinkMqProperties props) {
|
||||
Map<String, SinkMqProperties.Binding> configured = props.getConsumer().getBindings();
|
||||
private Map<String, KafkaSinkProperties.Binding> effectiveBindings(KafkaSinkProperties props) {
|
||||
Map<String, KafkaSinkProperties.Binding> configured = props.getConsumer().getBindings();
|
||||
if (configured != null && !configured.isEmpty()) {
|
||||
return configured;
|
||||
}
|
||||
// 默认绑定仅给未显式配置 bindings 的轻量运行时兜底。
|
||||
// 生产 history app 会显式绑定各协议 event/raw topic,并写入 TDengine raw_frames/locations。
|
||||
SinkMqProperties.Topics topics = props.getTopics();
|
||||
Map<String, SinkMqProperties.Binding> defaults = new LinkedHashMap<>();
|
||||
KafkaSinkProperties.Topics topics = props.getTopics();
|
||||
Map<String, KafkaSinkProperties.Binding> defaults = new LinkedHashMap<>();
|
||||
defaults.put("eventHistoryEnvelopeConsumerProcessor", binding(
|
||||
"vehicle-event-history",
|
||||
topics.getRealtime(), topics.getLocation(), topics.getAlarm(), topics.getSession(), topics.getMediaMeta()));
|
||||
@@ -78,8 +78,8 @@ public final class KafkaEnvelopeConsumerFactory {
|
||||
return defaults;
|
||||
}
|
||||
|
||||
private SinkMqProperties.Binding binding(String groupId, String... topics) {
|
||||
SinkMqProperties.Binding binding = new SinkMqProperties.Binding();
|
||||
private KafkaSinkProperties.Binding binding(String groupId, String... topics) {
|
||||
KafkaSinkProperties.Binding binding = new KafkaSinkProperties.Binding();
|
||||
binding.setGroupId(groupId);
|
||||
binding.setTopics(List.of(topics));
|
||||
return binding;
|
||||
@@ -106,12 +106,12 @@ public final class KafkaEnvelopeConsumerFactory {
|
||||
return List.copyOf(clean);
|
||||
}
|
||||
|
||||
private Properties consumerProperties(SinkMqProperties props,
|
||||
SinkMqProperties.Binding binding,
|
||||
private Properties consumerProperties(KafkaSinkProperties props,
|
||||
KafkaSinkProperties.Binding binding,
|
||||
String processorBeanName,
|
||||
int workerIndex,
|
||||
int concurrency) {
|
||||
SinkMqProperties.Consumer consumer = props.getConsumer();
|
||||
KafkaSinkProperties.Consumer consumer = props.getConsumer();
|
||||
Properties p = new Properties();
|
||||
p.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, props.getBootstrapServers());
|
||||
p.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
|
||||
@@ -133,7 +133,7 @@ public final class KafkaEnvelopeConsumerFactory {
|
||||
return concurrency <= 1 ? base : base + "-" + workerIndex;
|
||||
}
|
||||
|
||||
private String groupId(SinkMqProperties.Binding binding, String processorBeanName) {
|
||||
private String groupId(KafkaSinkProperties.Binding binding, String processorBeanName) {
|
||||
if (binding.getGroupId() != null && !binding.getGroupId().isBlank()) {
|
||||
return binding.getGroupId();
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeConsumerProcessor;
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeConsumerRecord;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeDeadLetterRecord;
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeDeadLetterSink;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import com.lingniu.ingest.api.event.VehicleEvent;
|
||||
import com.lingniu.ingest.api.sink.EventSink;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
|
||||
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
|
||||
@@ -16,40 +16,31 @@ import java.time.Duration;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* MQ Sink 自动装配。
|
||||
* Kafka Sink 自动装配。
|
||||
*
|
||||
* <p>装配前提(两个条件都要满足):
|
||||
* <ol>
|
||||
* <li>{@code lingniu.ingest.sink.mq.enabled=true}(默认 true)—— <b>总开关</b>,
|
||||
* 设为 false 时本模块完全不装配,ingest-core 的 DisruptorEventBus 仍然运行但
|
||||
* 没有 Kafka sink。
|
||||
* <li>{@code lingniu.ingest.sink.mq.type=kafka}(默认 kafka)—— 唯一生产 MQ 后端。
|
||||
* </ol>
|
||||
*
|
||||
* <p>Producer 和 Consumer 是两个独立开关:{@code sink.mq.enabled=true} 只表示可以创建
|
||||
* Kafka producer/sink;是否从 Kafka 拉 envelope 还要单独开启
|
||||
* {@code lingniu.ingest.sink.mq.consumer.enabled=true} 并配置 bindings。
|
||||
* <p>{@code lingniu.ingest.sink.kafka.enabled=false} 时本模块完全不装配;Producer 和 Consumer
|
||||
* 是两个独立开关,消费端还需要开启 {@code lingniu.ingest.sink.kafka.consumer.enabled=true}
|
||||
* 并配置 bindings。
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@EnableConfigurationProperties(SinkMqProperties.class)
|
||||
@ConditionalOnProperty(prefix = "lingniu.ingest.sink.mq", name = "enabled", havingValue = "true", matchIfMissing = true)
|
||||
public class SinkMqAutoConfiguration {
|
||||
@EnableConfigurationProperties(KafkaSinkProperties.class)
|
||||
@ConditionalOnProperty(prefix = "lingniu.ingest.sink.kafka", name = "enabled", havingValue = "true", matchIfMissing = true)
|
||||
public class KafkaSinkAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EnvelopeMapper envelopeMapper(SinkMqProperties props) {
|
||||
public EnvelopeMapper envelopeMapper(KafkaSinkProperties props) {
|
||||
return new EnvelopeMapper(props.getNodeId());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TopicRouter topicRouter(SinkMqProperties props) {
|
||||
public TopicRouter topicRouter(KafkaSinkProperties props) {
|
||||
return new TopicRouter(props.getTopics());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty(prefix = "lingniu.ingest.sink.mq", name = "type", havingValue = "kafka", matchIfMissing = true)
|
||||
public CircuitBreaker kafkaSinkCircuitBreaker() {
|
||||
return CircuitBreaker.of("kafka-sink", CircuitBreakerConfig.custom()
|
||||
.slidingWindowSize(100)
|
||||
@@ -61,8 +52,7 @@ public class SinkMqAutoConfiguration {
|
||||
|
||||
@Bean(destroyMethod = "close")
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty(prefix = "lingniu.ingest.sink.mq", name = "type", havingValue = "kafka", matchIfMissing = true)
|
||||
public KafkaProducer<String, byte[]> kafkaProducer(SinkMqProperties props) {
|
||||
public KafkaProducer<String, byte[]> kafkaProducer(KafkaSinkProperties props) {
|
||||
Properties p = new Properties();
|
||||
p.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, props.getBootstrapServers());
|
||||
p.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
|
||||
@@ -77,11 +67,10 @@ public class SinkMqAutoConfiguration {
|
||||
|
||||
@Bean(destroyMethod = "close")
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty(prefix = "lingniu.ingest.sink.mq", name = "type", havingValue = "kafka", matchIfMissing = true)
|
||||
public KafkaEventSink kafkaEventSink(KafkaProducer<String, byte[]> producer,
|
||||
EnvelopeMapper mapper,
|
||||
TopicRouter router,
|
||||
SinkMqProperties props,
|
||||
KafkaSinkProperties props,
|
||||
CircuitBreaker breaker) {
|
||||
// KafkaEventSink 是 EventBus 的生产端出口;它不会启动任何 Kafka 消费线程。
|
||||
return new KafkaEventSink(producer, mapper, router, props.getTopics().getDlq(), breaker);
|
||||
@@ -89,9 +78,8 @@ public class SinkMqAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty(prefix = "lingniu.ingest.sink.mq", name = "type", havingValue = "kafka", matchIfMissing = true)
|
||||
public KafkaEnvelopeDeadLetterSink kafkaEnvelopeDeadLetterSink(KafkaProducer<String, byte[]> producer,
|
||||
SinkMqProperties props) {
|
||||
KafkaSinkProperties props) {
|
||||
return new KafkaEnvelopeDeadLetterSink(producer, props.getTopics().getDlq());
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeConsumerProcessor;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
@@ -13,15 +13,15 @@ import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@AutoConfiguration(after = SinkMqAutoConfiguration.class)
|
||||
@AutoConfiguration(after = KafkaSinkAutoConfiguration.class)
|
||||
@AutoConfigureAfter(name = {
|
||||
"com.lingniu.ingest.eventhistory.config.EventHistoryAutoConfiguration",
|
||||
"com.lingniu.ingest.vehiclestate.config.VehicleStateAutoConfiguration",
|
||||
"com.lingniu.ingest.vehiclestat.config.VehicleStatAutoConfiguration"
|
||||
})
|
||||
@EnableConfigurationProperties(SinkMqProperties.class)
|
||||
@ConditionalOnProperty(prefix = "lingniu.ingest.sink.mq", name = "enabled", havingValue = "true", matchIfMissing = true)
|
||||
public class SinkMqConsumerAutoConfiguration {
|
||||
@EnableConfigurationProperties(KafkaSinkProperties.class)
|
||||
@ConditionalOnProperty(prefix = "lingniu.ingest.sink.kafka", name = "enabled", havingValue = "true", matchIfMissing = true)
|
||||
public class KafkaSinkConsumerAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@@ -31,10 +31,10 @@ public class SinkMqConsumerAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty(prefix = "lingniu.ingest.sink.mq.consumer", name = "enabled", havingValue = "true")
|
||||
@ConditionalOnProperty(prefix = "lingniu.ingest.sink.kafka.consumer", name = "enabled", havingValue = "true")
|
||||
public KafkaEnvelopeConsumerRunner kafkaEnvelopeConsumerRunner(ListableBeanFactory beanFactory,
|
||||
KafkaEnvelopeConsumerFactory consumerFactory,
|
||||
SinkMqProperties props) {
|
||||
KafkaSinkProperties props) {
|
||||
return new KafkaEnvelopeConsumerRunner(
|
||||
() -> createWorkers(beanFactory, consumerFactory, props),
|
||||
Duration.ofMillis(props.getConsumer().getPollTimeoutMillis()),
|
||||
@@ -44,7 +44,7 @@ public class SinkMqConsumerAutoConfiguration {
|
||||
|
||||
private List<KafkaEnvelopeConsumerWorker> createWorkers(ListableBeanFactory beanFactory,
|
||||
KafkaEnvelopeConsumerFactory consumerFactory,
|
||||
SinkMqProperties props) {
|
||||
KafkaSinkProperties props) {
|
||||
Map<String, EnvelopeConsumerProcessor> processors = beanFactory.getBeansOfType(EnvelopeConsumerProcessor.class);
|
||||
return consumerFactory.createWorkers(processors, props);
|
||||
}
|
||||
@@ -1,26 +1,23 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
@ConfigurationProperties(prefix = "lingniu.ingest.sink.mq")
|
||||
public class SinkMqProperties {
|
||||
@ConfigurationProperties(prefix = "lingniu.ingest.sink.kafka")
|
||||
public class KafkaSinkProperties {
|
||||
|
||||
/**
|
||||
* MQ Sink 总开关。默认 {@code true}。
|
||||
* 设为 {@code false} 时 {@link SinkMqAutoConfiguration} 完全不装配任何 Bean(Kafka Producer、
|
||||
* Kafka Sink 总开关。默认 {@code true}。
|
||||
* 设为 {@code false} 时 {@link KafkaSinkAutoConfiguration} 完全不装配任何 Bean(Kafka Producer、
|
||||
* EnvelopeMapper、TopicRouter、KafkaEventSink 都不会创建),ingest-core 的 DisruptorEventBus
|
||||
* 仍然正常运行但没有外部 sink(事件落地到 sink-archive 或 Noop 吞掉)。
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
/** MQ 后端类型。生产链路只允许 kafka。 */
|
||||
private String type = "kafka";
|
||||
/** Kafka bootstrap servers;生产环境应通过环境变量覆盖,不建议使用默认开发地址。 */
|
||||
private String bootstrapServers = "114.55.58.251:9092";
|
||||
private String compressionType = "zstd";
|
||||
@@ -35,14 +32,6 @@ public class SinkMqProperties {
|
||||
|
||||
public boolean isEnabled() { return enabled; }
|
||||
public void setEnabled(boolean enabled) { this.enabled = enabled; }
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) {
|
||||
String value = type == null || type.isBlank() ? "kafka" : type.trim().toLowerCase(Locale.ROOT);
|
||||
if (!"kafka".equals(value)) {
|
||||
throw new IllegalStateException("sink.mq.type supports only kafka; configured value: " + type);
|
||||
}
|
||||
this.type = value;
|
||||
}
|
||||
public String getBootstrapServers() { return bootstrapServers; }
|
||||
public void setBootstrapServers(String bootstrapServers) { this.bootstrapServers = bootstrapServers; }
|
||||
public String getCompressionType() { return compressionType; }
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import com.lingniu.ingest.api.event.VehicleEvent;
|
||||
|
||||
@@ -7,9 +7,9 @@ import com.lingniu.ingest.api.event.VehicleEvent;
|
||||
*/
|
||||
public final class TopicRouter {
|
||||
|
||||
private final SinkMqProperties.Topics topics;
|
||||
private final KafkaSinkProperties.Topics topics;
|
||||
|
||||
public TopicRouter(SinkMqProperties.Topics topics) {
|
||||
public TopicRouter(KafkaSinkProperties.Topics topics) {
|
||||
this.topics = topics;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package com.lingniu.ingest.sink.mq.proto;
|
||||
package com.lingniu.ingest.sink.kafka.proto;
|
||||
|
||||
option java_multiple_files = true;
|
||||
option java_package = "com.lingniu.ingest.sink.mq.proto";
|
||||
option java_package = "com.lingniu.ingest.sink.kafka.proto";
|
||||
option java_outer_classname = "VehicleEnvelopeProto";
|
||||
|
||||
// 统一消息外壳:所有 Topic 共用此 Envelope,payload 通过 oneof 区分具体事件类型。
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
com.lingniu.ingest.sink.mq.SinkMqAutoConfiguration
|
||||
com.lingniu.ingest.sink.mq.SinkMqConsumerAutoConfiguration
|
||||
com.lingniu.ingest.sink.kafka.KafkaSinkAutoConfiguration
|
||||
com.lingniu.ingest.sink.kafka.KafkaSinkConsumerAutoConfiguration
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import com.lingniu.ingest.api.ProtocolId;
|
||||
import com.lingniu.ingest.api.event.RawArchiveKeys;
|
||||
import com.lingniu.ingest.api.event.RealtimePayload;
|
||||
import com.lingniu.ingest.api.event.VehicleEvent;
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.Instant;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeConsumerProcessor;
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeIngestResult;
|
||||
@@ -23,7 +23,7 @@ class KafkaEnvelopeConsumerFactoryTest {
|
||||
created.add(props);
|
||||
return new MockConsumer<>(OffsetResetStrategy.EARLIEST);
|
||||
});
|
||||
SinkMqProperties props = new SinkMqProperties();
|
||||
KafkaSinkProperties props = new KafkaSinkProperties();
|
||||
props.setBootstrapServers("kafka-1:9092");
|
||||
EnvelopeConsumerProcessor stateProcessor = processor();
|
||||
EnvelopeConsumerProcessor statProcessor = processor();
|
||||
@@ -51,7 +51,7 @@ class KafkaEnvelopeConsumerFactoryTest {
|
||||
created.add(props);
|
||||
return new MockConsumer<>(OffsetResetStrategy.EARLIEST);
|
||||
});
|
||||
SinkMqProperties props = new SinkMqProperties();
|
||||
KafkaSinkProperties props = new KafkaSinkProperties();
|
||||
props.getConsumer().setConcurrency(3);
|
||||
EnvelopeConsumerProcessor stateProcessor = processor();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeConsumerRecord;
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeBatchIngestor;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeDeadLetterRecord;
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeIngestResult;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import com.lingniu.ingest.api.ProtocolId;
|
||||
import com.lingniu.ingest.api.event.LocationPayload;
|
||||
@@ -26,7 +26,7 @@ class KafkaEventSinkTest {
|
||||
KafkaEventSink sink = new KafkaEventSink(
|
||||
null,
|
||||
new EnvelopeMapper("node-1"),
|
||||
new TopicRouter(new SinkMqProperties.Topics()),
|
||||
new TopicRouter(new KafkaSinkProperties.Topics()),
|
||||
"vehicle.dlq.gb32960.v1",
|
||||
CircuitBreaker.ofDefaults("kafka-test"));
|
||||
|
||||
@@ -46,7 +46,7 @@ class KafkaEventSinkTest {
|
||||
KafkaEventSink sink = new KafkaEventSink(
|
||||
producer,
|
||||
new EnvelopeMapper("node-1"),
|
||||
new TopicRouter(new SinkMqProperties.Topics()),
|
||||
new TopicRouter(new KafkaSinkProperties.Topics()),
|
||||
"vehicle.dlq.gb32960.v1",
|
||||
CircuitBreaker.ofDefaults("kafka-test"));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeConsumerProcessor;
|
||||
import com.lingniu.ingest.api.consumer.EnvelopeIngestResult;
|
||||
@@ -15,26 +15,25 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
@ExtendWith(OutputCaptureExtension.class)
|
||||
class SinkMqConsumerAutoConfigurationTest {
|
||||
class KafkaSinkConsumerAutoConfigurationTest {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withUserConfiguration(SinkMqAutoConfiguration.class, SinkMqConsumerAutoConfiguration.class)
|
||||
.withUserConfiguration(KafkaSinkAutoConfiguration.class, KafkaSinkConsumerAutoConfiguration.class)
|
||||
.withAllowBeanDefinitionOverriding(true)
|
||||
.withBean("vehicleStateEnvelopeConsumerProcessor", EnvelopeConsumerProcessor.class,
|
||||
() -> new EnvelopeConsumerProcessor(
|
||||
"vehicle-state",
|
||||
bytes -> EnvelopeIngestResult.processed("evt-1", "VIN001"),
|
||||
record -> {}))
|
||||
.withBean("kafkaProducer", KafkaProducer.class, SinkMqConsumerAutoConfigurationTest::kafkaProducer)
|
||||
.withBean("kafkaProducer", KafkaProducer.class, KafkaSinkConsumerAutoConfigurationTest::kafkaProducer)
|
||||
.withBean(KafkaEnvelopeConsumerFactory.class,
|
||||
() -> new KafkaEnvelopeConsumerFactory(props -> new MockConsumer<>(OffsetResetStrategy.EARLIEST)))
|
||||
.withPropertyValues(
|
||||
"lingniu.ingest.sink.mq.enabled=true",
|
||||
"lingniu.ingest.sink.mq.type=kafka",
|
||||
"lingniu.ingest.sink.mq.consumer.enabled=true",
|
||||
"lingniu.ingest.sink.mq.consumer.auto-startup=false",
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.vehicleStateEnvelopeConsumerProcessor.group-id=vehicle-state",
|
||||
"lingniu.ingest.sink.mq.consumer.bindings.vehicleStateEnvelopeConsumerProcessor.topics[0]=vehicle.realtime");
|
||||
"lingniu.ingest.sink.kafka.enabled=true",
|
||||
"lingniu.ingest.sink.kafka.consumer.enabled=true",
|
||||
"lingniu.ingest.sink.kafka.consumer.auto-startup=false",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.vehicleStateEnvelopeConsumerProcessor.group-id=vehicle-state",
|
||||
"lingniu.ingest.sink.kafka.consumer.bindings.vehicleStateEnvelopeConsumerProcessor.topics[0]=vehicle.realtime");
|
||||
|
||||
@Test
|
||||
void createsKafkaEnvelopeConsumerRunnerWhenConsumerBindingIsConfigured(CapturedOutput output) {
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class KafkaSinkPropertiesTest {
|
||||
|
||||
@Test
|
||||
void defaultKafkaBrokerUsesProductionAddressButCanStillBeOverriddenByConfigBinding() {
|
||||
KafkaSinkProperties props = new KafkaSinkProperties();
|
||||
|
||||
assertThat(props.getBootstrapServers()).isEqualTo("114.55.58.251:9092");
|
||||
|
||||
props.setBootstrapServers("kafka.internal:9092");
|
||||
assertThat(props.getBootstrapServers()).isEqualTo("kafka.internal:9092");
|
||||
}
|
||||
|
||||
@Test
|
||||
void exposesNoBackendTypeBecauseKafkaIsTheOnlySink() {
|
||||
assertThat(Arrays.stream(KafkaSinkProperties.class.getMethods()).map(method -> method.getName()))
|
||||
.doesNotContain("getType", "setType");
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import com.lingniu.ingest.api.ProtocolId;
|
||||
import com.lingniu.ingest.api.event.AlarmPayload;
|
||||
@@ -18,14 +18,14 @@ class TopicRouterTest {
|
||||
|
||||
@Test
|
||||
void rawArchiveRoutesToVersionedGb32960RawTopicByDefault() {
|
||||
TopicRouter router = new TopicRouter(new SinkMqProperties.Topics());
|
||||
TopicRouter router = new TopicRouter(new KafkaSinkProperties.Topics());
|
||||
|
||||
assertThat(router.route(rawArchive())).isEqualTo("vehicle.raw.gb32960.v1");
|
||||
}
|
||||
|
||||
@Test
|
||||
void normalizedGb32960EventsRouteToVersionedEventTopicByDefault() {
|
||||
TopicRouter router = new TopicRouter(new SinkMqProperties.Topics());
|
||||
TopicRouter router = new TopicRouter(new KafkaSinkProperties.Topics());
|
||||
|
||||
assertThat(router.route(realtime())).isEqualTo("vehicle.event.gb32960.v1");
|
||||
assertThat(router.route(location())).isEqualTo("vehicle.event.gb32960.v1");
|
||||
@@ -37,7 +37,7 @@ class TopicRouterTest {
|
||||
|
||||
@Test
|
||||
void dlqDefaultsToVersionedGb32960DlqTopic() {
|
||||
SinkMqProperties.Topics topics = new SinkMqProperties.Topics();
|
||||
KafkaSinkProperties.Topics topics = new KafkaSinkProperties.Topics();
|
||||
|
||||
assertThat(topics.getDlq()).isEqualTo("vehicle.dlq.gb32960.v1");
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
package com.lingniu.ingest.sink.kafka;
|
||||
|
||||
import com.lingniu.ingest.sink.mq.proto.DecodedFactPayload;
|
||||
import com.lingniu.ingest.sink.mq.proto.ParseStatusProto;
|
||||
import com.lingniu.ingest.sink.mq.proto.RawFrameFactPayload;
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.proto.DecodedFactPayload;
|
||||
import com.lingniu.ingest.sink.kafka.proto.ParseStatusProto;
|
||||
import com.lingniu.ingest.sink.kafka.proto.RawFrameFactPayload;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -1,29 +0,0 @@
|
||||
package com.lingniu.ingest.sink.mq;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
class SinkMqPropertiesTest {
|
||||
|
||||
@Test
|
||||
void defaultKafkaBrokerUsesProductionAddressButCanStillBeOverriddenByConfigBinding() {
|
||||
SinkMqProperties props = new SinkMqProperties();
|
||||
|
||||
assertThat(props.getBootstrapServers()).isEqualTo("114.55.58.251:9092");
|
||||
|
||||
props.setBootstrapServers("kafka.internal:9092");
|
||||
assertThat(props.getBootstrapServers()).isEqualTo("kafka.internal:9092");
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsUnsupportedMqTypeInsteadOfSilentlyDisablingKafkaBeans() {
|
||||
SinkMqProperties props = new SinkMqProperties();
|
||||
|
||||
assertThatThrownBy(() -> props.setType("rocketmq"))
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessageContaining("sink.mq.type supports only kafka")
|
||||
.hasMessageContaining("rocketmq");
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,10 @@ package com.lingniu.ingest.tdenginehistory;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.lingniu.ingest.sink.mq.proto.LocationPayload;
|
||||
import com.lingniu.ingest.sink.mq.proto.RawFrameFactPayload;
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.proto.LocationPayload;
|
||||
import com.lingniu.ingest.sink.kafka.proto.RawFrameFactPayload;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.lingniu.ingest.tdenginehistory;
|
||||
|
||||
import com.lingniu.ingest.sink.mq.proto.LocationPayload;
|
||||
import com.lingniu.ingest.sink.mq.proto.ParseStatusProto;
|
||||
import com.lingniu.ingest.sink.mq.proto.RawArchiveRef;
|
||||
import com.lingniu.ingest.sink.mq.proto.RawFrameFactPayload;
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.mq.proto.TelemetrySnapshot;
|
||||
import com.lingniu.ingest.sink.mq.proto.VehicleEnvelope;
|
||||
import com.lingniu.ingest.sink.kafka.proto.LocationPayload;
|
||||
import com.lingniu.ingest.sink.kafka.proto.ParseStatusProto;
|
||||
import com.lingniu.ingest.sink.kafka.proto.RawArchiveRef;
|
||||
import com.lingniu.ingest.sink.kafka.proto.RawFrameFactPayload;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetryField;
|
||||
import com.lingniu.ingest.sink.kafka.proto.TelemetrySnapshot;
|
||||
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
Reference in New Issue
Block a user