diff --git a/src/java/src/main/java/org/openapitools/config/DataSourceConfig.java b/src/java/src/main/java/org/openapitools/config/DataSourceConfig.java index e9e58862..32e3e9d4 100644 --- a/src/java/src/main/java/org/openapitools/config/DataSourceConfig.java +++ b/src/java/src/main/java/org/openapitools/config/DataSourceConfig.java @@ -206,12 +206,25 @@ private void configureCloudSqlProperties(HikariConfig config, String jdbcUrl) { config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.postgres.SocketFactory"); config.addDataSourceProperty("unixSocketPath", instanceUnixSocket); + String cloudSqlInstance = extractCloudSqlInstance(instanceUnixSocket); + if (isNotBlank(cloudSqlInstance)) { + config.addDataSourceProperty("cloudSqlInstance", cloudSqlInstance); + } if (isCloudRun()) { config.addDataSourceProperty("cloudSqlRefreshStrategy", "lazy"); } } + private String extractCloudSqlInstance(String unixSocketPath) { + final String prefix = "/cloudsql/"; + if (!isNotBlank(unixSocketPath) || !unixSocketPath.startsWith(prefix)) { + return null; + } + String instanceConnectionName = unixSocketPath.substring(prefix.length()); + return isNotBlank(instanceConnectionName) ? instanceConnectionName : null; + } + private String extractUnixSocketPath(String jdbcUrl) { String rawQuery = extractRawQuery(jdbcUrl); if (!isNotBlank(rawQuery)) { diff --git a/src/java/src/test/java/org/openapitools/config/DataSourceConfigTest.java b/src/java/src/test/java/org/openapitools/config/DataSourceConfigTest.java index 6cef1c35..01c15608 100644 --- a/src/java/src/test/java/org/openapitools/config/DataSourceConfigTest.java +++ b/src/java/src/test/java/org/openapitools/config/DataSourceConfigTest.java @@ -95,6 +95,7 @@ void hikariConfig_ShouldNormalizeCloudSqlSocketStyleDatabaseUrl() throws Excepti assertThat(result.getDataSourceProperties()) .containsEntry("socketFactory", "com.google.cloud.sql.postgres.SocketFactory") .containsEntry("unixSocketPath", "/cloudsql/project-id:region:instance-id") + .containsEntry("cloudSqlInstance", "project-id:region:instance-id") .doesNotContainKey("cloudSqlRefreshStrategy"); } @@ -120,6 +121,7 @@ void hikariConfig_ShouldSetCloudSqlRefreshStrategyOnCloudRunInSocketMode() throw assertThat(result.getDataSourceProperties()) .containsEntry("socketFactory", "com.google.cloud.sql.postgres.SocketFactory") .containsEntry("unixSocketPath", "/cloudsql/project-id:region:instance-id") + .containsEntry("cloudSqlInstance", "project-id:region:instance-id") .containsEntry("cloudSqlRefreshStrategy", "lazy"); } diff --git a/src/kotlin/src/main/kotlin/com/lampcontrol/database/DatabaseFactory.kt b/src/kotlin/src/main/kotlin/com/lampcontrol/database/DatabaseFactory.kt index 4c98cdfa..90b737b4 100644 --- a/src/kotlin/src/main/kotlin/com/lampcontrol/database/DatabaseFactory.kt +++ b/src/kotlin/src/main/kotlin/com/lampcontrol/database/DatabaseFactory.kt @@ -76,6 +76,10 @@ object DatabaseFactory { hikariConfig.addDataSourceProperty("socketFactory", CLOUD_SQL_SOCKET_FACTORY) hikariConfig.addDataSourceProperty("unixSocketPath", config.host) + val cloudSqlInstance = extractCloudSqlInstance(config.host) + if (cloudSqlInstance != null) { + hikariConfig.addDataSourceProperty("cloudSqlInstance", cloudSqlInstance) + } val cloudRunService = System.getenv("K_SERVICE") val cloudRunRevision = System.getenv("K_REVISION") @@ -83,6 +87,11 @@ object DatabaseFactory { hikariConfig.addDataSourceProperty("cloudSqlRefreshStrategy", "lazy") } } + + private fun extractCloudSqlInstance(unixSocketPath: String): String? { + val instance = unixSocketPath.removePrefix(CLOUD_SQL_PATH_PREFIX) + return instance.takeIf { it.isNotBlank() } + } } /** diff --git a/src/kotlin/src/test/kotlin/com/lampcontrol/database/DatabaseFactoryTest.kt b/src/kotlin/src/test/kotlin/com/lampcontrol/database/DatabaseFactoryTest.kt index 0195f05a..35824871 100644 --- a/src/kotlin/src/test/kotlin/com/lampcontrol/database/DatabaseFactoryTest.kt +++ b/src/kotlin/src/test/kotlin/com/lampcontrol/database/DatabaseFactoryTest.kt @@ -1,6 +1,8 @@ package com.lampcontrol.database +import com.zaxxer.hikari.HikariConfig import org.junit.jupiter.api.Test +import kotlin.test.assertEquals import kotlin.test.assertNotNull class DatabaseFactoryTest { @@ -32,4 +34,44 @@ class DatabaseFactoryTest { // Verify DatabaseFactory object can be accessed assertNotNull(DatabaseFactory) } + + @Test + fun `configureCloudSqlProperties sets cloudSqlInstance from unix socket path`() { + val hikariConfig = HikariConfig() + val config = + DatabaseConfig( + host = "/cloudsql/project:region:instance-id", + port = 5432, + database = "lamp-control", + user = "postgres", + password = "secret", + poolMin = 0, + poolMax = 4, + maxLifetimeMs = 3600000, + idleTimeoutMs = 1800000, + connectionTimeoutMs = 30000, + ) + + val configureMethod = + DatabaseFactory::class.java.getDeclaredMethod( + "configureCloudSqlProperties", + HikariConfig::class.java, + DatabaseConfig::class.java, + ) + configureMethod.isAccessible = true + configureMethod.invoke(DatabaseFactory, hikariConfig, config) + + assertEquals( + "com.google.cloud.sql.postgres.SocketFactory", + hikariConfig.dataSourceProperties["socketFactory"], + ) + assertEquals( + "/cloudsql/project:region:instance-id", + hikariConfig.dataSourceProperties["unixSocketPath"], + ) + assertEquals( + "project:region:instance-id", + hikariConfig.dataSourceProperties["cloudSqlInstance"], + ) + } }