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

zqr10159 pushed a commit to branch 2.0.0
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git

commit e1d8eb0627424a25abc52eb27601997c58ddbe5b
Author: Logic <[email protected]>
AuthorDate: Tue Aug 25 20:01:18 2026 +0800

    fix: restore managed database startup
---
 .../manager/config/FlywayConfiguration.java        | 32 ++--------------------
 .../config/ApplicationConfigDocumentCodec.java     | 21 ++++++++++++++
 .../manager/config/FlywayConfigurationTest.java    | 26 ++++++++++++++++++
 ...anagedOptionalConfigurationPersistenceTest.java | 25 +++++++++++++++++
 4 files changed, 75 insertions(+), 29 deletions(-)

diff --git 
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/config/FlywayConfiguration.java
 
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/config/FlywayConfiguration.java
index 394767407e..1f47692214 100644
--- 
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/config/FlywayConfiguration.java
+++ 
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/config/FlywayConfiguration.java
@@ -20,43 +20,17 @@ package org.apache.hertzbeat.manager.config;
 import org.flywaydb.core.Flyway;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import 
org.springframework.boot.flyway.autoconfigure.FlywayMigrationInitializer;
-import org.springframework.boot.flyway.autoconfigure.FlywayProperties;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.DependsOn;
 
-/**
- * Flyway database migration config.
- * Delays Flyway execution until after Hibernate has created/updated the 
schema.
- */
+/** Runs Flyway before JPA so empty databases use the current baseline 
migration. */
 @Configuration
 @ConditionalOnProperty(prefix = "spring.flyway", name = "enabled", havingValue 
= "true")
 public class FlywayConfiguration {
 
-    /**
-     * Disable the default FlywayMigrationInitializer by providing an empty 
callback.
-     */
+    /** Retains an explicit initializer while preserving Spring Boot's 
migrate-before-JPA contract. */
     @Bean
     public FlywayMigrationInitializer flywayInitializer(Flyway flyway) {
-        return new FlywayMigrationInitializer(flyway, (f) -> {
-            // Empty callback - we'll run migrations manually after Hibernate
-        });
-    }
-
-    /**
-     * Delayed Flyway migration that runs after EntityManagerFactory is 
initialized.
-     * This ensures Hibernate's ddl-auto runs first to create/update tables,
-     * then Flyway can perform additional migrations if needed.
-     */
-    @Bean
-    @DependsOn("entityManagerFactory")
-    Dummy delayedFlywayInitializer(Flyway flyway, FlywayProperties 
flywayProperties) {
-        if (flywayProperties.isEnabled()) {
-            flyway.migrate();
-        }
-        return new Dummy();
-    }
-
-    static class Dummy {
+        return new FlywayMigrationInitializer(flyway);
     }
 }
diff --git 
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/setup/config/ApplicationConfigDocumentCodec.java
 
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/setup/config/ApplicationConfigDocumentCodec.java
index f7e2284fd7..ea950ca8fd 100644
--- 
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/setup/config/ApplicationConfigDocumentCodec.java
+++ 
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/setup/config/ApplicationConfigDocumentCodec.java
@@ -51,6 +51,8 @@ final class ApplicationConfigDocumentCodec implements 
ManagedDocumentCodec<Manag
 
     // This exact flat-key allowlist is the boundary that prevents setup from 
becoming an arbitrary YAML editor.
     private static final String DUCKDB_ENABLED = 
"warehouse.store.duckdb.enabled";
+    private static final String DATASOURCE_DRIVER = 
"spring.datasource.driver-class-name";
+    private static final String HIBERNATE_DIALECT = 
"spring.jpa.properties.hibernate.dialect";
     private static final String MAIL_PORT = "spring.mail.port";
     private static final String MAIL_USERNAME = "spring.mail.username";
     private static final String MANAGED_SERVER_PROFILE_ID = "server-direct";
@@ -79,9 +81,28 @@ final class ApplicationConfigDocumentCodec implements 
ManagedDocumentCodec<Manag
         Map<String, Object> properties = new LinkedHashMap<>();
         plainProperties(value).forEach(
                 (key, item) -> properties.put(key, 
Integrity.literalForSpring(item)));
+        MetadataDatabaseKind kind = value.metadataDatabase().kind();
+        properties.put(DATASOURCE_DRIVER, driverFor(kind));
+        properties.put(HIBERNATE_DIALECT, dialectFor(kind));
         return Map.copyOf(properties);
     }
 
+    private static String driverFor(MetadataDatabaseKind kind) {
+        return switch (kind) {
+            case H2 -> "org.h2.Driver";
+            case MYSQL -> "com.mysql.cj.jdbc.Driver";
+            case POSTGRESQL -> "org.postgresql.Driver";
+        };
+    }
+
+    private static String dialectFor(MetadataDatabaseKind kind) {
+        return switch (kind) {
+            case H2 -> "org.hibernate.dialect.H2Dialect";
+            case MYSQL -> "org.hibernate.dialect.MySQLDialect";
+            case POSTGRESQL -> "org.hibernate.dialect.PostgreSQLDialect";
+        };
+    }
+
     private static Map<String, String> 
plainProperties(ManagedApplicationConfig value) {
         Map<String, String> values = new LinkedHashMap<>();
         values.put(DATASOURCE_URL, value.metadataDatabase().jdbcUrl());
diff --git 
a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/config/FlywayConfigurationTest.java
 
b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/config/FlywayConfigurationTest.java
new file mode 100644
index 0000000000..0582d931ba
--- /dev/null
+++ 
b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/config/FlywayConfigurationTest.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0.
+ */
+
+package org.apache.hertzbeat.manager.config;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import org.flywaydb.core.Flyway;
+import org.junit.jupiter.api.Test;
+
+class FlywayConfigurationTest {
+
+    @Test
+    void migratesBeforeJpaInsteadOfWaitingForHibernateSchemaMutation() throws 
Exception {
+        Flyway flyway = mock(Flyway.class);
+
+        new 
FlywayConfiguration().flywayInitializer(flyway).afterPropertiesSet();
+
+        verify(flyway).migrate();
+    }
+}
diff --git 
a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/setup/config/ManagedOptionalConfigurationPersistenceTest.java
 
b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/setup/config/ManagedOptionalConfigurationPersistenceTest.java
index 84bb49ae96..db51dc9d64 100644
--- 
a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/setup/config/ManagedOptionalConfigurationPersistenceTest.java
+++ 
b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/setup/config/ManagedOptionalConfigurationPersistenceTest.java
@@ -30,6 +30,23 @@ class ManagedOptionalConfigurationPersistenceTest {
     @TempDir
     private java.nio.file.Path root;
 
+    @Test
+    void materializesTheDriverAndHibernateDialectForEachManagedDatabaseKind() {
+        assertThat(databaseProperties(MetadataDatabaseKind.H2, 
"jdbc:h2:./data/hertzbeat"))
+                .containsEntry("spring.datasource.driver-class-name", 
"org.h2.Driver")
+                .containsEntry("spring.jpa.database", "H2")
+                .containsEntry("spring.jpa.properties.hibernate.dialect", 
"org.hibernate.dialect.H2Dialect");
+        assertThat(databaseProperties(MetadataDatabaseKind.MYSQL, 
"jdbc:mysql://db/hertzbeat"))
+                .containsEntry("spring.datasource.driver-class-name", 
"com.mysql.cj.jdbc.Driver")
+                .containsEntry("spring.jpa.database", "MYSQL")
+                .containsEntry("spring.jpa.properties.hibernate.dialect", 
"org.hibernate.dialect.MySQLDialect");
+        assertThat(databaseProperties(MetadataDatabaseKind.POSTGRESQL, 
"jdbc:postgresql://db/hertzbeat"))
+                .containsEntry("spring.datasource.driver-class-name", 
"org.postgresql.Driver")
+                .containsEntry("spring.jpa.database", "POSTGRESQL")
+                .containsEntry("spring.jpa.properties.hibernate.dialect",
+                        "org.hibernate.dialect.PostgreSQLDialect");
+    }
+
     @Test
     void 
optionsUpdatePreservesRequiredSettingsAndStoresMailPasswordOnlyInSecrets() 
throws Exception {
         ManagedConfigurationTransaction transaction = new 
ManagedConfigurationTransaction(root);
@@ -175,4 +192,12 @@ class ManagedOptionalConfigurationPersistenceTest {
         return new ManagedConfigurationBundle(application,
                 
ManagedSecrets.withoutTelemetryPassword(SecretValue.of("database-secret")));
     }
+
+    private static java.util.Map<String, Object> databaseProperties(
+            MetadataDatabaseKind kind, String jdbcUrl) {
+        return ApplicationConfigDocumentCodec.springProperties(new 
ManagedApplicationConfig(
+                new MetadataDatabaseSettings(kind, jdbcUrl, "hertzbeat"),
+                GreptimeSettings.anonymous(
+                        new GreptimeEndpoints("localhost:4001", 
"http://localhost:4000";), "public")));
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to