Fix production credit service wiring

Register the credits service through its route-facing interface and verify the application module resolves the binding without touching MySQL.
This commit is contained in:
Rocky
2026-08-16 19:39:06 +08:00
parent a17d058748
commit c415c53a1c
2 changed files with 56 additions and 0 deletions
@@ -34,6 +34,7 @@ import com.osglab.account.features.credits.repositories.BillingTransactionRunner
import com.osglab.account.features.credits.repositories.ExposedBillingTransactionRunner import com.osglab.account.features.credits.repositories.ExposedBillingTransactionRunner
import com.osglab.account.features.credits.routes.AuthenticatedUserExtractor import com.osglab.account.features.credits.routes.AuthenticatedUserExtractor
import com.osglab.account.features.credits.routes.creditRoutes import com.osglab.account.features.credits.routes.creditRoutes
import com.osglab.account.features.credits.services.CreditOperations
import com.osglab.account.features.credits.services.CreditService import com.osglab.account.features.credits.services.CreditService
import com.osglab.account.features.credits.services.ReferralRewardConfig import com.osglab.account.features.credits.services.ReferralRewardConfig
import com.osglab.account.features.gateway.adapters.CreditReservationAdapter import com.osglab.account.features.gateway.adapters.CreditReservationAdapter
@@ -336,6 +337,7 @@ fun accountServerModule(config: AppConfig): Module = module {
), ),
) )
} }
single<CreditOperations> { get<CreditService>() }
single<TrialCreditGranter> { single<TrialCreditGranter> {
TrialCreditGranter { accountId -> TrialCreditGranter { accountId ->
get<CreditService>().grantSignupTrial( get<CreditService>().grantSignupTrial(
@@ -1,10 +1,19 @@
package com.osglab.account package com.osglab.account
import com.osglab.account.config.AppConfig
import com.osglab.account.features.credits.repositories.BillingTransactionRunner
import com.osglab.account.features.credits.repositories.BillingUnitOfWork
import com.osglab.account.features.credits.services.CreditOperations
import com.osglab.account.features.credits.services.CreditService
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe
import io.ktor.client.request.get import io.ktor.client.request.get
import io.ktor.http.HttpStatusCode import io.ktor.http.HttpStatusCode
import io.ktor.server.config.MapApplicationConfig
import io.ktor.server.routing.routing import io.ktor.server.routing.routing
import io.ktor.server.testing.testApplication import io.ktor.server.testing.testApplication
import org.koin.dsl.koinApplication
import org.koin.dsl.module
import java.util.Base64
import kotlin.test.Test import kotlin.test.Test
class ApplicationTest { class ApplicationTest {
@@ -16,4 +25,49 @@ class ApplicationTest {
client.get("/health/live").status shouldBe HttpStatusCode.OK client.get("/health/live").status shouldBe HttpStatusCode.OK
} }
@Test
fun `application module exposes credit operations through its interface`() {
val transactionRunner = object : BillingTransactionRunner {
override suspend fun <T> inTransaction(block: (BillingUnitOfWork) -> T): T =
error("Transaction runner is not used while resolving dependencies")
}
val application = koinApplication {
allowOverride(true)
modules(accountServerModule(testModuleConfig()))
modules(module { single<BillingTransactionRunner> { transactionRunner } })
}
try {
application.koin.get<CreditOperations>() shouldBe
application.koin.get<CreditService>()
} finally {
application.close()
}
}
} }
private fun testModuleConfig(): AppConfig = AppConfig.from(
MapApplicationConfig(
"app.environment" to "test",
"app.database.jdbcUrl" to "jdbc:mysql://localhost:3306/test",
"app.database.username" to "test",
"app.database.password" to "database-password",
"app.database.migrationUsername" to "test_migrator",
"app.database.migrationPassword" to "migration-password",
"app.database.maximumPoolSize" to "4",
"app.session.issuer" to "https://issuer.example",
"app.session.audience" to "ios-app",
"app.session.secret" to "01234567890123456789012345678901",
"app.session.accessMinutes" to "15",
"app.session.refreshDays" to "30",
"app.encryption.keyBase64" to Base64.getEncoder().encodeToString(ByteArray(32) { 7 }),
"app.antiAbuse.identityHmacKeyBase64" to Base64.getEncoder().encodeToString(ByteArray(32) { 8 }),
"app.apple.clientId" to "com.example.app",
"app.apple.jwksUrl" to "https://appleid.apple.com/auth/keys",
"app.apple.tokenUrl" to "https://appleid.apple.com/auth/token",
"app.apple.revokeUrl" to "https://appleid.apple.com/auth/revoke",
"app.integrity.enforceDeviceCheck" to "false",
"app.integrity.enforceAppAttest" to "false",
),
)