From e246e29d315a6205179c0a57a9cdcc6d4705e997 Mon Sep 17 00:00:00 2001 From: Jason Yoo Date: Tue, 16 Jul 2024 00:24:15 +0900 Subject: [PATCH 1/9] feat: impl server log --- .../user/application/build.gradle.kts | 3 +++ .../port/in/UserApplicationService.kt | 8 ++++-- .../user/infra/build.gradle.kts | 1 + .../in/controller/UpdateUserInfoTest.kt | 9 +++++++ .../application/server_log/build.gradle.kts | 4 +++ .../server_log/port/in/SccServerLogger.kt | 7 +++++ .../port/in/SccServerPersistentLogger.kt | 27 +++++++++++++++++++ .../out/persistence/ServerLogRepository.kt | 7 +++++ .../domain/server_log/build.gradle.kts | 4 +++ .../NewsletterSubscribedOnSignupPayload.kt | 7 +++++ .../domain/server_log/ServerLog.kt | 10 +++++++ .../domain/server_log/ServerLogPayload.kt | 5 ++++ .../domain/server_log/ServerLogType.kt | 5 ++++ .../infra/persistence_model/build.gradle.kts | 1 + .../infra/persistence/sqldelight/DB.kt | 25 +++++++++++++++++ .../migration/V26__add_server_log.sqm | 12 +++++++++ .../sqldelight/query/server_log/ServerLog.sq | 8 ++++++ .../infra/server_log/build.gradle.kts | 6 +++++ .../out/persistence/ServerLogRepository.kt | 19 +++++++++++++ .../out/persistence/sqldelight/Converters.kt | 19 +++++++++++++ 20 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 app-server/subprojects/cross_cutting_concern/application/server_log/build.gradle.kts create mode 100644 app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/in/SccServerLogger.kt create mode 100644 app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/in/SccServerPersistentLogger.kt create mode 100644 app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/out/persistence/ServerLogRepository.kt create mode 100644 app-server/subprojects/cross_cutting_concern/domain/server_log/build.gradle.kts create mode 100644 app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/NewsletterSubscribedOnSignupPayload.kt create mode 100644 app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLog.kt create mode 100644 app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLogPayload.kt create mode 100644 app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLogType.kt create mode 100644 app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/migration/V26__add_server_log.sqm create mode 100644 app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/query/server_log/ServerLog.sq create mode 100644 app-server/subprojects/cross_cutting_concern/infra/server_log/build.gradle.kts create mode 100644 app-server/subprojects/cross_cutting_concern/infra/server_log/src/main/kotlin/club/staircrusher/infra/server_log/out/persistence/ServerLogRepository.kt create mode 100644 app-server/subprojects/cross_cutting_concern/infra/server_log/src/main/kotlin/club/staircrusher/infra/server_log/out/persistence/sqldelight/Converters.kt diff --git a/app-server/subprojects/bounded_context/user/application/build.gradle.kts b/app-server/subprojects/bounded_context/user/application/build.gradle.kts index e69de29bb..7d49ea34e 100644 --- a/app-server/subprojects/bounded_context/user/application/build.gradle.kts +++ b/app-server/subprojects/bounded_context/user/application/build.gradle.kts @@ -0,0 +1,3 @@ +dependencies { + implementation(projects.crossCuttingConcern.application.serverLog) +} diff --git a/app-server/subprojects/bounded_context/user/application/src/main/kotlin/club/staircrusher/user/application/port/in/UserApplicationService.kt b/app-server/subprojects/bounded_context/user/application/src/main/kotlin/club/staircrusher/user/application/port/in/UserApplicationService.kt index 13c281232..84b86aea4 100644 --- a/app-server/subprojects/bounded_context/user/application/src/main/kotlin/club/staircrusher/user/application/port/in/UserApplicationService.kt +++ b/app-server/subprojects/bounded_context/user/application/src/main/kotlin/club/staircrusher/user/application/port/in/UserApplicationService.kt @@ -1,5 +1,7 @@ package club.staircrusher.user.application.port.`in` +import club.staircrusher.application.server_log.port.`in`.SccServerLogger +import club.staircrusher.domain.server_log.NewsletterSubscribedOnSignupPayload import club.staircrusher.stdlib.clock.SccClock import club.staircrusher.stdlib.di.annotation.Component import club.staircrusher.stdlib.domain.SccDomainException @@ -25,6 +27,7 @@ class UserApplicationService( private val passwordEncryptor: PasswordEncryptor, private val userAuthInfoRepository: UserAuthInfoRepository, private val stibeeSubscriptionService: StibeeSubscriptionService, + private val sccServerLogger: SccServerLogger, ) { @Deprecated("닉네임 로그인은 사라질 예정") @@ -133,7 +136,7 @@ class UserApplicationService( if (isNewsLetterSubscriptionAgreed) { transactionManager.doAfterCommit { - user.email?.let { subscribeToNewsLetter(it, user.nickname) } + user.email?.let { subscribeToNewsLetter(user.id, it, user.nickname) } } } @@ -162,7 +165,8 @@ class UserApplicationService( return userRepository.findAll() } - private fun subscribeToNewsLetter(email: String, name: String) { + private fun subscribeToNewsLetter(userId: String, email: String, name: String) { + sccServerLogger.record(NewsletterSubscribedOnSignupPayload(userId)) runBlocking { stibeeSubscriptionService.registerSubscriber( email = email, diff --git a/app-server/subprojects/bounded_context/user/infra/build.gradle.kts b/app-server/subprojects/bounded_context/user/infra/build.gradle.kts index c9606121d..88164b595 100644 --- a/app-server/subprojects/bounded_context/user/infra/build.gradle.kts +++ b/app-server/subprojects/bounded_context/user/infra/build.gradle.kts @@ -20,5 +20,6 @@ dependencies { implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinxSerializationVersion") integrationTestImplementation(projects.crossCuttingConcern.test.springIt) + integrationTestImplementation(projects.crossCuttingConcern.application.serverLog) testImplementation("org.mockito.kotlin:mockito-kotlin:5.1.0") } diff --git a/app-server/subprojects/bounded_context/user/infra/src/integrationTest/kotlin/club/staircrusher/user/infra/adapter/in/controller/UpdateUserInfoTest.kt b/app-server/subprojects/bounded_context/user/infra/src/integrationTest/kotlin/club/staircrusher/user/infra/adapter/in/controller/UpdateUserInfoTest.kt index e20061a9c..5ac29ea7a 100644 --- a/app-server/subprojects/bounded_context/user/infra/src/integrationTest/kotlin/club/staircrusher/user/infra/adapter/in/controller/UpdateUserInfoTest.kt +++ b/app-server/subprojects/bounded_context/user/infra/src/integrationTest/kotlin/club/staircrusher/user/infra/adapter/in/controller/UpdateUserInfoTest.kt @@ -3,6 +3,8 @@ package club.staircrusher.user.infra.adapter.`in`.controller import club.staircrusher.api.spec.dto.ApiErrorResponse import club.staircrusher.api.spec.dto.UpdateUserInfoPost200Response import club.staircrusher.api.spec.dto.UpdateUserInfoPostRequest +import club.staircrusher.application.server_log.port.`in`.SccServerLogger +import club.staircrusher.domain.server_log.NewsletterSubscribedOnSignupPayload import club.staircrusher.stdlib.testing.SccRandom import club.staircrusher.user.application.port.out.web.subscription.StibeeSubscriptionService import club.staircrusher.user.domain.model.UserMobilityTool @@ -16,6 +18,7 @@ import org.mockito.kotlin.any import org.mockito.kotlin.atLeastOnce import org.mockito.kotlin.eq import org.mockito.kotlin.never +import org.mockito.kotlin.verify import org.mockito.kotlin.verifyBlocking import org.springframework.boot.test.mock.mockito.MockBean @@ -23,6 +26,9 @@ class UpdateUserInfoTest : UserITBase() { @MockBean lateinit var stibeeSubscriptionService: StibeeSubscriptionService + @MockBean + lateinit var sccServerLogger: SccServerLogger + @Test fun updateUserInfoTest() { val user = transactionManager.doInTransaction { @@ -196,6 +202,7 @@ class UpdateUserInfoTest : UserITBase() { } .apply { verifyBlocking(stibeeSubscriptionService, atLeastOnce()) { registerSubscriber(eq(changedEmail), eq(changedNickname), any()) } + verify(sccServerLogger, atLeastOnce()).record(NewsletterSubscribedOnSignupPayload(user.id)) } } @@ -230,6 +237,7 @@ class UpdateUserInfoTest : UserITBase() { } .apply { verifyBlocking(stibeeSubscriptionService, never()) { registerSubscriber(eq(changedEmail), eq(changedNickname), any()) } + verify(sccServerLogger, never()).record(NewsletterSubscribedOnSignupPayload(user.id)) } } @@ -265,6 +273,7 @@ class UpdateUserInfoTest : UserITBase() { } .apply { verifyBlocking(stibeeSubscriptionService, never()) { registerSubscriber(eq(changedEmail), eq(changedNickname), any()) } + verify(sccServerLogger, never()).record(NewsletterSubscribedOnSignupPayload(user.id)) } } } diff --git a/app-server/subprojects/cross_cutting_concern/application/server_log/build.gradle.kts b/app-server/subprojects/cross_cutting_concern/application/server_log/build.gradle.kts new file mode 100644 index 000000000..8c977d453 --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/application/server_log/build.gradle.kts @@ -0,0 +1,4 @@ +dependencies { + implementation(rootProject.projects.crossCuttingConcern.stdlib) + api(rootProject.projects.crossCuttingConcern.domain.serverLog) +} diff --git a/app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/in/SccServerLogger.kt b/app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/in/SccServerLogger.kt new file mode 100644 index 000000000..93acbfd93 --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/in/SccServerLogger.kt @@ -0,0 +1,7 @@ +package club.staircrusher.application.server_log.port.`in` + +import club.staircrusher.domain.server_log.ServerLogPayload + +interface SccServerLogger { + fun record(payload: ServerLogPayload) +} diff --git a/app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/in/SccServerPersistentLogger.kt b/app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/in/SccServerPersistentLogger.kt new file mode 100644 index 000000000..da8ad427f --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/in/SccServerPersistentLogger.kt @@ -0,0 +1,27 @@ +package club.staircrusher.application.server_log.port.`in` + +import club.staircrusher.application.server_log.port.out.persistence.ServerLogRepository +import club.staircrusher.domain.server_log.ServerLog +import club.staircrusher.domain.server_log.ServerLogPayload +import club.staircrusher.stdlib.clock.SccClock +import club.staircrusher.stdlib.di.annotation.Component +import club.staircrusher.stdlib.domain.entity.EntityIdGenerator +import club.staircrusher.stdlib.persistence.TransactionManager + +@Component +class SccServerPersistentLogger( + private val transactionManager: TransactionManager, + private val serverLogRepository: ServerLogRepository, +) : SccServerLogger { + override fun record(payload: ServerLogPayload) = transactionManager.doInTransaction { + val serverLog = ServerLog( + id = EntityIdGenerator.generateRandom(), + type = payload.type, + payload = payload, + createdAt = SccClock.instant(), + ) + + serverLogRepository.save(serverLog) + Unit + } +} diff --git a/app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/out/persistence/ServerLogRepository.kt b/app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/out/persistence/ServerLogRepository.kt new file mode 100644 index 000000000..f51c06595 --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/out/persistence/ServerLogRepository.kt @@ -0,0 +1,7 @@ +package club.staircrusher.application.server_log.port.out.persistence + +import club.staircrusher.domain.server_log.ServerLog + +interface ServerLogRepository { + fun save(entity: ServerLog): ServerLog +} diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_log/build.gradle.kts b/app-server/subprojects/cross_cutting_concern/domain/server_log/build.gradle.kts new file mode 100644 index 000000000..2fcbb0129 --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/domain/server_log/build.gradle.kts @@ -0,0 +1,4 @@ +dependencies { + val kotlinxSerializationVersion: String by project + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinxSerializationVersion") +} diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/NewsletterSubscribedOnSignupPayload.kt b/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/NewsletterSubscribedOnSignupPayload.kt new file mode 100644 index 000000000..2d88324a1 --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/NewsletterSubscribedOnSignupPayload.kt @@ -0,0 +1,7 @@ +package club.staircrusher.domain.server_log + +data class NewsletterSubscribedOnSignupPayload( + val userId: String, +) : ServerLogPayload { + override val type = ServerLogType.NEWSLETTER_SUBSCRIBED_ON_SIGN_UP +} diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLog.kt b/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLog.kt new file mode 100644 index 000000000..c14237c82 --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLog.kt @@ -0,0 +1,10 @@ +package club.staircrusher.domain.server_log + +import java.time.Instant + +data class ServerLog( + val id: String, + val type: ServerLogType, + val payload: ServerLogPayload, + val createdAt: Instant, +) diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLogPayload.kt b/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLogPayload.kt new file mode 100644 index 000000000..252a0acf6 --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLogPayload.kt @@ -0,0 +1,5 @@ +package club.staircrusher.domain.server_log + +interface ServerLogPayload { + val type: ServerLogType +} diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLogType.kt b/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLogType.kt new file mode 100644 index 000000000..d8629a10a --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLogType.kt @@ -0,0 +1,5 @@ +package club.staircrusher.domain.server_log + +enum class ServerLogType { + NEWSLETTER_SUBSCRIBED_ON_SIGN_UP, +} diff --git a/app-server/subprojects/cross_cutting_concern/infra/persistence_model/build.gradle.kts b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/build.gradle.kts index fe720ca68..446f05711 100644 --- a/app-server/subprojects/cross_cutting_concern/infra/persistence_model/build.gradle.kts +++ b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/build.gradle.kts @@ -9,6 +9,7 @@ dependencies { implementation(projects.boundedContext.challenge.domain) implementation(projects.boundedContext.quest.domain) implementation(projects.boundedContext.user.domain) + implementation(projects.crossCuttingConcern.domain.serverLog) val sqlDelightVersion: String by project api("app.cash.sqldelight:runtime-jvm:$sqlDelightVersion") diff --git a/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/kotlin/club/staircrusher/infra/persistence/sqldelight/DB.kt b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/kotlin/club/staircrusher/infra/persistence/sqldelight/DB.kt index 592cd0ebe..40e609013 100644 --- a/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/kotlin/club/staircrusher/infra/persistence/sqldelight/DB.kt +++ b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/kotlin/club/staircrusher/infra/persistence/sqldelight/DB.kt @@ -1,6 +1,9 @@ package club.staircrusher.infra.persistence.sqldelight +import app.cash.sqldelight.ColumnAdapter import club.staircrusher.challenge.domain.model.ChallengeCondition +import club.staircrusher.domain.server_log.ServerLogPayload +import club.staircrusher.domain.server_log.ServerLogType import club.staircrusher.infra.persistence.sqldelight.column_adapter.AccessibilityImageListStringColumnAdapter import club.staircrusher.infra.persistence.sqldelight.column_adapter.ClubQuestPurposeTypeStringColumnAdapter import club.staircrusher.infra.persistence.sqldelight.column_adapter.EntranceDoorTypeListStringColumnAdapter @@ -19,6 +22,7 @@ import club.staircrusher.infra.persistence.sqldelight.migration.Club_quest import club.staircrusher.infra.persistence.sqldelight.migration.Place import club.staircrusher.infra.persistence.sqldelight.migration.Place_accessibility import club.staircrusher.infra.persistence.sqldelight.migration.Scc_user +import club.staircrusher.infra.persistence.sqldelight.migration.Server_log import club.staircrusher.infra.persistence.sqldelight.migration.User_auth_info import club.staircrusher.stdlib.di.annotation.Component import club.staircrusher.stdlib.persistence.Transaction @@ -79,6 +83,26 @@ class DB(dataSource: DataSource) : TransactionManager { ), club_questAdapter = Club_quest.Adapter( purpose_typeAdapter = ClubQuestPurposeTypeStringColumnAdapter, + ), + server_logAdapter = Server_log.Adapter( + typeAdapter = object : ColumnAdapter { + override fun decode(databaseValue: String): ServerLogType { + return ServerLogType.valueOf(databaseValue) + } + + override fun encode(value: ServerLogType): String { + return value.name + } + }, + payloadAdapter = object : ColumnAdapter { + override fun decode(databaseValue: String): ServerLogPayload { + return objectMapper.readValue(databaseValue) + } + + override fun encode(value: ServerLogPayload): String { + return objectMapper.writeValueAsString(value) + } + } ) ) @@ -102,6 +126,7 @@ class DB(dataSource: DataSource) : TransactionManager { val challengeContributionQueries = scc.challengeContributionQueries val challengeParticipationQueries = scc.challengeParticipationQueries val challengeRankQueries = scc.challengeRankQueries + val serverLogQueries = scc.serverLogQueries override fun doInTransaction(block: Transaction.() -> T): T { diff --git a/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/migration/V26__add_server_log.sqm b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/migration/V26__add_server_log.sqm new file mode 100644 index 000000000..c8da2fd05 --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/migration/V26__add_server_log.sqm @@ -0,0 +1,12 @@ +import club.staircrusher.domain.server_log.ServerLogPayload; +import club.staircrusher.domain.server_log.ServerLogType; + +CREATE TABLE IF NOT EXISTS server_log ( + id VARCHAR(36) NOT NULL, + type VARCHAR(64) AS ServerLogType NOT NULL, + payload TEXT AS ServerLogPayload NOT NULL DEFAULT '', + created_at TIMESTAMP(6) WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (id) +); + +CREATE INDEX idx_server_log_1 ON server_log(type, created_at); \ No newline at end of file diff --git a/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/query/server_log/ServerLog.sq b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/query/server_log/ServerLog.sq new file mode 100644 index 000000000..8f24227ca --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/query/server_log/ServerLog.sq @@ -0,0 +1,8 @@ +save: +INSERT INTO server_log +VALUES :server_log +ON CONFLICT(id) DO UPDATE SET + id = EXCLUDED.id, + type = EXCLUDED.type, + payload = EXCLUDED.payload, + created_at = EXCLUDED.created_at; \ No newline at end of file diff --git a/app-server/subprojects/cross_cutting_concern/infra/server_log/build.gradle.kts b/app-server/subprojects/cross_cutting_concern/infra/server_log/build.gradle.kts new file mode 100644 index 000000000..ce05752da --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/infra/server_log/build.gradle.kts @@ -0,0 +1,6 @@ +dependencies { + implementation(projects.crossCuttingConcern.stdlib) + implementation(projects.crossCuttingConcern.infra.persistenceModel) + api(rootProject.projects.crossCuttingConcern.domain.serverLog) + api(rootProject.projects.crossCuttingConcern.application.serverLog) +} diff --git a/app-server/subprojects/cross_cutting_concern/infra/server_log/src/main/kotlin/club/staircrusher/infra/server_log/out/persistence/ServerLogRepository.kt b/app-server/subprojects/cross_cutting_concern/infra/server_log/src/main/kotlin/club/staircrusher/infra/server_log/out/persistence/ServerLogRepository.kt new file mode 100644 index 000000000..18bcb7d89 --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/infra/server_log/src/main/kotlin/club/staircrusher/infra/server_log/out/persistence/ServerLogRepository.kt @@ -0,0 +1,19 @@ +package club.staircrusher.infra.server_log.out.persistence + +import club.staircrusher.application.server_log.port.out.persistence.ServerLogRepository +import club.staircrusher.domain.server_log.ServerLog +import club.staircrusher.infra.persistence.sqldelight.DB +import club.staircrusher.infra.server_log.out.persistence.sqldelight.toPersistenceModel +import club.staircrusher.stdlib.di.annotation.Component + +@Component +class ServerLogRepository( + db: DB, +) : ServerLogRepository { + private val queries = db.serverLogQueries + + override fun save(entity: ServerLog): ServerLog { + queries.save(entity.toPersistenceModel()) + return entity + } +} diff --git a/app-server/subprojects/cross_cutting_concern/infra/server_log/src/main/kotlin/club/staircrusher/infra/server_log/out/persistence/sqldelight/Converters.kt b/app-server/subprojects/cross_cutting_concern/infra/server_log/src/main/kotlin/club/staircrusher/infra/server_log/out/persistence/sqldelight/Converters.kt new file mode 100644 index 000000000..c3309f3c4 --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/infra/server_log/src/main/kotlin/club/staircrusher/infra/server_log/out/persistence/sqldelight/Converters.kt @@ -0,0 +1,19 @@ +package club.staircrusher.infra.server_log.out.persistence.sqldelight + +import club.staircrusher.domain.server_log.ServerLog +import club.staircrusher.infra.persistence.sqldelight.migration.Server_log +import club.staircrusher.stdlib.time.toOffsetDateTime + +fun ServerLog.toPersistenceModel() = Server_log( + id = id, + type = type, + payload = payload, + created_at = createdAt.toOffsetDateTime(), +) + +fun Server_log.toDomainModel() = ServerLog( + id = id, + type = type, + payload = payload, + createdAt = created_at.toInstant(), +) From e253d7f5054cf5e66e87ecd17578a5f8421fbe37 Mon Sep 17 00:00:00 2001 From: Jason Yoo Date: Tue, 16 Jul 2024 00:44:23 +0900 Subject: [PATCH 2/9] refactor: add newline --- .../persistence/sqldelight/migration/V26__add_server_log.sqm | 2 +- .../infra/persistence/sqldelight/query/server_log/ServerLog.sq | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/migration/V26__add_server_log.sqm b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/migration/V26__add_server_log.sqm index c8da2fd05..6850486ad 100644 --- a/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/migration/V26__add_server_log.sqm +++ b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/migration/V26__add_server_log.sqm @@ -9,4 +9,4 @@ CREATE TABLE IF NOT EXISTS server_log ( PRIMARY KEY (id) ); -CREATE INDEX idx_server_log_1 ON server_log(type, created_at); \ No newline at end of file +CREATE INDEX idx_server_log_1 ON server_log(type, created_at); diff --git a/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/query/server_log/ServerLog.sq b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/query/server_log/ServerLog.sq index 8f24227ca..9041ded9f 100644 --- a/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/query/server_log/ServerLog.sq +++ b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/query/server_log/ServerLog.sq @@ -5,4 +5,4 @@ ON CONFLICT(id) DO UPDATE SET id = EXCLUDED.id, type = EXCLUDED.type, payload = EXCLUDED.payload, - created_at = EXCLUDED.created_at; \ No newline at end of file + created_at = EXCLUDED.created_at; From c3417d2aae3a123151c1a244243ce9bfe4e3cdd3 Mon Sep 17 00:00:00 2001 From: Jason Yoo Date: Tue, 16 Jul 2024 00:58:35 +0900 Subject: [PATCH 3/9] fix: dependency graph --- .../subprojects/bounded_context/user/infra/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-server/subprojects/bounded_context/user/infra/build.gradle.kts b/app-server/subprojects/bounded_context/user/infra/build.gradle.kts index 88164b595..4d2316431 100644 --- a/app-server/subprojects/bounded_context/user/infra/build.gradle.kts +++ b/app-server/subprojects/bounded_context/user/infra/build.gradle.kts @@ -9,6 +9,7 @@ dependencies { api(projects.apiSpecification.api) implementation(projects.crossCuttingConcern.infra.persistenceModel) + implementation(projects.crossCuttingConcern.infra.serverLog) implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework:spring-webflux") implementation("io.projectreactor.netty:reactor-netty") @@ -20,6 +21,5 @@ dependencies { implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinxSerializationVersion") integrationTestImplementation(projects.crossCuttingConcern.test.springIt) - integrationTestImplementation(projects.crossCuttingConcern.application.serverLog) testImplementation("org.mockito.kotlin:mockito-kotlin:5.1.0") } From 98c0150bf2e8639e5e16fdd322012de851faf39d Mon Sep 17 00:00:00 2001 From: Jason Yoo Date: Tue, 16 Jul 2024 01:10:05 +0900 Subject: [PATCH 4/9] test: add mocking --- .../infra/spring_web/build.gradle.kts | 1 + .../spring_web/mock/MockServerLogRepository.kt | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 app-server/subprojects/cross_cutting_concern/infra/spring_web/src/integrationTest/kotlin/club/staircrusher/spring_web/mock/MockServerLogRepository.kt diff --git a/app-server/subprojects/cross_cutting_concern/infra/spring_web/build.gradle.kts b/app-server/subprojects/cross_cutting_concern/infra/spring_web/build.gradle.kts index be8905d14..d9da6b741 100644 --- a/app-server/subprojects/cross_cutting_concern/infra/spring_web/build.gradle.kts +++ b/app-server/subprojects/cross_cutting_concern/infra/spring_web/build.gradle.kts @@ -18,4 +18,5 @@ dependencies { implementation("com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonModuleKotlinVersion") integrationTestImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonModuleKotlinVersion") integrationTestImplementation("org.springframework.boot:spring-boot-starter-test") + integrationTestImplementation(projects.crossCuttingConcern.application.serverLog) } diff --git a/app-server/subprojects/cross_cutting_concern/infra/spring_web/src/integrationTest/kotlin/club/staircrusher/spring_web/mock/MockServerLogRepository.kt b/app-server/subprojects/cross_cutting_concern/infra/spring_web/src/integrationTest/kotlin/club/staircrusher/spring_web/mock/MockServerLogRepository.kt new file mode 100644 index 000000000..664b5ee88 --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/infra/spring_web/src/integrationTest/kotlin/club/staircrusher/spring_web/mock/MockServerLogRepository.kt @@ -0,0 +1,17 @@ +package club.staircrusher.spring_web.mock + +import club.staircrusher.application.server_log.port.out.persistence.ServerLogRepository +import club.staircrusher.domain.server_log.ServerLog +import club.staircrusher.stdlib.di.annotation.Component + +@Component +class MockServerLogRepository : ServerLogRepository { + override fun save(entity: ServerLog): ServerLog { + return ServerLog( + id = entity.id, + type = entity.type, + payload = entity.payload, + createdAt = entity.createdAt + ) + } +} From 0857cc98e82f358e30376d8e62f2812966f8854d Mon Sep 17 00:00:00 2001 From: Jason Yoo Date: Wed, 17 Jul 2024 17:28:12 +0900 Subject: [PATCH 5/9] refactor: log -> event --- .../user/application/build.gradle.kts | 2 +- .../port/in/UserApplicationService.kt | 8 +++--- .../user/infra/build.gradle.kts | 2 +- .../in/controller/UpdateUserInfoTest.kt | 12 ++++----- .../build.gradle.kts | 2 +- .../port/in/SccServerEventRecorder.kt | 7 +++++ .../in/SccServerPersistentEventRecorder.kt | 27 +++++++++++++++++++ .../out/persistence/ServerEventRepository.kt | 7 +++++ .../server_log/port/in/SccServerLogger.kt | 7 ----- .../port/in/SccServerPersistentLogger.kt | 27 ------------------- .../out/persistence/ServerLogRepository.kt | 7 ----- .../build.gradle.kts | 0 .../NewsletterSubscribedOnSignupPayload.kt | 7 +++++ .../domain/server_event/ServerEvent.kt | 10 +++++++ .../domain/server_event/ServerEventPayload.kt | 5 ++++ .../domain/server_event/ServerEventType.kt | 5 ++++ .../NewsletterSubscribedOnSignupPayload.kt | 7 ----- .../domain/server_log/ServerLog.kt | 10 ------- .../domain/server_log/ServerLogPayload.kt | 5 ---- .../domain/server_log/ServerLogType.kt | 5 ---- .../infra/persistence_model/build.gradle.kts | 2 +- .../infra/persistence/sqldelight/DB.kt | 24 ++++++++--------- .../migration/V26__add_server_event.sqm | 13 +++++++++ .../migration/V26__add_server_log.sqm | 12 --------- .../ServerEvent.sq} | 4 +-- .../build.gradle.kts | 4 +-- .../out/persistence/ServerEventRepository.kt | 19 +++++++++++++ .../out/persistence/sqldelight/Converters.kt | 10 +++---- .../out/persistence/ServerLogRepository.kt | 19 ------------- .../infra/spring_web/build.gradle.kts | 2 +- .../mock/MockServerEventRepository.kt | 17 ++++++++++++ .../mock/MockServerLogRepository.kt | 17 ------------ 32 files changed, 153 insertions(+), 152 deletions(-) rename app-server/subprojects/cross_cutting_concern/application/{server_log => server_event}/build.gradle.kts (55%) create mode 100644 app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerEventRecorder.kt create mode 100644 app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerPersistentEventRecorder.kt create mode 100644 app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/out/persistence/ServerEventRepository.kt delete mode 100644 app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/in/SccServerLogger.kt delete mode 100644 app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/in/SccServerPersistentLogger.kt delete mode 100644 app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/out/persistence/ServerLogRepository.kt rename app-server/subprojects/cross_cutting_concern/domain/{server_log => server_event}/build.gradle.kts (100%) create mode 100644 app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/NewsletterSubscribedOnSignupPayload.kt create mode 100644 app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEvent.kt create mode 100644 app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventPayload.kt create mode 100644 app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventType.kt delete mode 100644 app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/NewsletterSubscribedOnSignupPayload.kt delete mode 100644 app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLog.kt delete mode 100644 app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLogPayload.kt delete mode 100644 app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLogType.kt create mode 100644 app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/migration/V26__add_server_event.sqm delete mode 100644 app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/migration/V26__add_server_log.sqm rename app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/query/{server_log/ServerLog.sq => server_event/ServerEvent.sq} (77%) rename app-server/subprojects/cross_cutting_concern/infra/{server_log => server_event}/build.gradle.kts (72%) create mode 100644 app-server/subprojects/cross_cutting_concern/infra/server_event/src/main/kotlin/club/staircrusher/infra/server_event/out/persistence/ServerEventRepository.kt rename app-server/subprojects/cross_cutting_concern/infra/{server_log/src/main/kotlin/club/staircrusher/infra/server_log => server_event/src/main/kotlin/club/staircrusher/infra/server_event}/out/persistence/sqldelight/Converters.kt (56%) delete mode 100644 app-server/subprojects/cross_cutting_concern/infra/server_log/src/main/kotlin/club/staircrusher/infra/server_log/out/persistence/ServerLogRepository.kt create mode 100644 app-server/subprojects/cross_cutting_concern/infra/spring_web/src/integrationTest/kotlin/club/staircrusher/spring_web/mock/MockServerEventRepository.kt delete mode 100644 app-server/subprojects/cross_cutting_concern/infra/spring_web/src/integrationTest/kotlin/club/staircrusher/spring_web/mock/MockServerLogRepository.kt diff --git a/app-server/subprojects/bounded_context/user/application/build.gradle.kts b/app-server/subprojects/bounded_context/user/application/build.gradle.kts index 7d49ea34e..4b3dd88f1 100644 --- a/app-server/subprojects/bounded_context/user/application/build.gradle.kts +++ b/app-server/subprojects/bounded_context/user/application/build.gradle.kts @@ -1,3 +1,3 @@ dependencies { - implementation(projects.crossCuttingConcern.application.serverLog) + implementation(projects.crossCuttingConcern.application.serverEvent) } diff --git a/app-server/subprojects/bounded_context/user/application/src/main/kotlin/club/staircrusher/user/application/port/in/UserApplicationService.kt b/app-server/subprojects/bounded_context/user/application/src/main/kotlin/club/staircrusher/user/application/port/in/UserApplicationService.kt index 84b86aea4..8a70b0af0 100644 --- a/app-server/subprojects/bounded_context/user/application/src/main/kotlin/club/staircrusher/user/application/port/in/UserApplicationService.kt +++ b/app-server/subprojects/bounded_context/user/application/src/main/kotlin/club/staircrusher/user/application/port/in/UserApplicationService.kt @@ -1,7 +1,7 @@ package club.staircrusher.user.application.port.`in` -import club.staircrusher.application.server_log.port.`in`.SccServerLogger -import club.staircrusher.domain.server_log.NewsletterSubscribedOnSignupPayload +import club.staircrusher.application.server_event.port.`in`.SccServerEventRecorder +import club.staircrusher.domain.server_event.NewsletterSubscribedOnSignupPayload import club.staircrusher.stdlib.clock.SccClock import club.staircrusher.stdlib.di.annotation.Component import club.staircrusher.stdlib.domain.SccDomainException @@ -27,7 +27,7 @@ class UserApplicationService( private val passwordEncryptor: PasswordEncryptor, private val userAuthInfoRepository: UserAuthInfoRepository, private val stibeeSubscriptionService: StibeeSubscriptionService, - private val sccServerLogger: SccServerLogger, + private val sccServerEventRecorder: SccServerEventRecorder, ) { @Deprecated("닉네임 로그인은 사라질 예정") @@ -166,7 +166,7 @@ class UserApplicationService( } private fun subscribeToNewsLetter(userId: String, email: String, name: String) { - sccServerLogger.record(NewsletterSubscribedOnSignupPayload(userId)) + sccServerEventRecorder.record(NewsletterSubscribedOnSignupPayload(userId)) runBlocking { stibeeSubscriptionService.registerSubscriber( email = email, diff --git a/app-server/subprojects/bounded_context/user/infra/build.gradle.kts b/app-server/subprojects/bounded_context/user/infra/build.gradle.kts index 4d2316431..a23e46018 100644 --- a/app-server/subprojects/bounded_context/user/infra/build.gradle.kts +++ b/app-server/subprojects/bounded_context/user/infra/build.gradle.kts @@ -9,7 +9,7 @@ dependencies { api(projects.apiSpecification.api) implementation(projects.crossCuttingConcern.infra.persistenceModel) - implementation(projects.crossCuttingConcern.infra.serverLog) + implementation(projects.crossCuttingConcern.infra.serverEvent) implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework:spring-webflux") implementation("io.projectreactor.netty:reactor-netty") diff --git a/app-server/subprojects/bounded_context/user/infra/src/integrationTest/kotlin/club/staircrusher/user/infra/adapter/in/controller/UpdateUserInfoTest.kt b/app-server/subprojects/bounded_context/user/infra/src/integrationTest/kotlin/club/staircrusher/user/infra/adapter/in/controller/UpdateUserInfoTest.kt index 5ac29ea7a..1f5f0a0da 100644 --- a/app-server/subprojects/bounded_context/user/infra/src/integrationTest/kotlin/club/staircrusher/user/infra/adapter/in/controller/UpdateUserInfoTest.kt +++ b/app-server/subprojects/bounded_context/user/infra/src/integrationTest/kotlin/club/staircrusher/user/infra/adapter/in/controller/UpdateUserInfoTest.kt @@ -3,8 +3,8 @@ package club.staircrusher.user.infra.adapter.`in`.controller import club.staircrusher.api.spec.dto.ApiErrorResponse import club.staircrusher.api.spec.dto.UpdateUserInfoPost200Response import club.staircrusher.api.spec.dto.UpdateUserInfoPostRequest -import club.staircrusher.application.server_log.port.`in`.SccServerLogger -import club.staircrusher.domain.server_log.NewsletterSubscribedOnSignupPayload +import club.staircrusher.application.server_event.port.`in`.SccServerEventRecorder +import club.staircrusher.domain.server_event.NewsletterSubscribedOnSignupPayload import club.staircrusher.stdlib.testing.SccRandom import club.staircrusher.user.application.port.out.web.subscription.StibeeSubscriptionService import club.staircrusher.user.domain.model.UserMobilityTool @@ -27,7 +27,7 @@ class UpdateUserInfoTest : UserITBase() { lateinit var stibeeSubscriptionService: StibeeSubscriptionService @MockBean - lateinit var sccServerLogger: SccServerLogger + lateinit var sccServerEventRecorder: SccServerEventRecorder @Test fun updateUserInfoTest() { @@ -202,7 +202,7 @@ class UpdateUserInfoTest : UserITBase() { } .apply { verifyBlocking(stibeeSubscriptionService, atLeastOnce()) { registerSubscriber(eq(changedEmail), eq(changedNickname), any()) } - verify(sccServerLogger, atLeastOnce()).record(NewsletterSubscribedOnSignupPayload(user.id)) + verify(sccServerEventRecorder, atLeastOnce()).record(NewsletterSubscribedOnSignupPayload(user.id)) } } @@ -237,7 +237,7 @@ class UpdateUserInfoTest : UserITBase() { } .apply { verifyBlocking(stibeeSubscriptionService, never()) { registerSubscriber(eq(changedEmail), eq(changedNickname), any()) } - verify(sccServerLogger, never()).record(NewsletterSubscribedOnSignupPayload(user.id)) + verify(sccServerEventRecorder, never()).record(NewsletterSubscribedOnSignupPayload(user.id)) } } @@ -273,7 +273,7 @@ class UpdateUserInfoTest : UserITBase() { } .apply { verifyBlocking(stibeeSubscriptionService, never()) { registerSubscriber(eq(changedEmail), eq(changedNickname), any()) } - verify(sccServerLogger, never()).record(NewsletterSubscribedOnSignupPayload(user.id)) + verify(sccServerEventRecorder, never()).record(NewsletterSubscribedOnSignupPayload(user.id)) } } } diff --git a/app-server/subprojects/cross_cutting_concern/application/server_log/build.gradle.kts b/app-server/subprojects/cross_cutting_concern/application/server_event/build.gradle.kts similarity index 55% rename from app-server/subprojects/cross_cutting_concern/application/server_log/build.gradle.kts rename to app-server/subprojects/cross_cutting_concern/application/server_event/build.gradle.kts index 8c977d453..1dc4ab346 100644 --- a/app-server/subprojects/cross_cutting_concern/application/server_log/build.gradle.kts +++ b/app-server/subprojects/cross_cutting_concern/application/server_event/build.gradle.kts @@ -1,4 +1,4 @@ dependencies { implementation(rootProject.projects.crossCuttingConcern.stdlib) - api(rootProject.projects.crossCuttingConcern.domain.serverLog) + api(rootProject.projects.crossCuttingConcern.domain.serverEvent) } diff --git a/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerEventRecorder.kt b/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerEventRecorder.kt new file mode 100644 index 000000000..b8f4fb562 --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerEventRecorder.kt @@ -0,0 +1,7 @@ +package club.staircrusher.application.server_event.port.`in` + +import club.staircrusher.domain.server_event.ServerEventPayload + +interface SccServerEventRecorder { + fun record(payload: ServerEventPayload) +} diff --git a/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerPersistentEventRecorder.kt b/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerPersistentEventRecorder.kt new file mode 100644 index 000000000..a96a2f575 --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerPersistentEventRecorder.kt @@ -0,0 +1,27 @@ +package club.staircrusher.application.server_event.port.`in` + +import club.staircrusher.application.server_event.port.out.persistence.ServerEventRepository +import club.staircrusher.domain.server_event.ServerEvent +import club.staircrusher.domain.server_event.ServerEventPayload +import club.staircrusher.stdlib.clock.SccClock +import club.staircrusher.stdlib.di.annotation.Component +import club.staircrusher.stdlib.domain.entity.EntityIdGenerator +import club.staircrusher.stdlib.persistence.TransactionManager + +@Component +class SccServerPersistentEventRecorder( + private val transactionManager: TransactionManager, + private val serverEventRepository: ServerEventRepository, +) : SccServerEventRecorder { + override fun record(payload: ServerEventPayload) = transactionManager.doInTransaction { + val serverEvent = ServerEvent( + id = EntityIdGenerator.generateRandom(), + type = payload.type, + payload = payload, + createdAt = SccClock.instant(), + ) + + serverEventRepository.save(serverEvent) + Unit + } +} diff --git a/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/out/persistence/ServerEventRepository.kt b/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/out/persistence/ServerEventRepository.kt new file mode 100644 index 000000000..10f11b5b3 --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/out/persistence/ServerEventRepository.kt @@ -0,0 +1,7 @@ +package club.staircrusher.application.server_event.port.out.persistence + +import club.staircrusher.domain.server_event.ServerEvent + +interface ServerEventRepository { + fun save(entity: ServerEvent): ServerEvent +} diff --git a/app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/in/SccServerLogger.kt b/app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/in/SccServerLogger.kt deleted file mode 100644 index 93acbfd93..000000000 --- a/app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/in/SccServerLogger.kt +++ /dev/null @@ -1,7 +0,0 @@ -package club.staircrusher.application.server_log.port.`in` - -import club.staircrusher.domain.server_log.ServerLogPayload - -interface SccServerLogger { - fun record(payload: ServerLogPayload) -} diff --git a/app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/in/SccServerPersistentLogger.kt b/app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/in/SccServerPersistentLogger.kt deleted file mode 100644 index da8ad427f..000000000 --- a/app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/in/SccServerPersistentLogger.kt +++ /dev/null @@ -1,27 +0,0 @@ -package club.staircrusher.application.server_log.port.`in` - -import club.staircrusher.application.server_log.port.out.persistence.ServerLogRepository -import club.staircrusher.domain.server_log.ServerLog -import club.staircrusher.domain.server_log.ServerLogPayload -import club.staircrusher.stdlib.clock.SccClock -import club.staircrusher.stdlib.di.annotation.Component -import club.staircrusher.stdlib.domain.entity.EntityIdGenerator -import club.staircrusher.stdlib.persistence.TransactionManager - -@Component -class SccServerPersistentLogger( - private val transactionManager: TransactionManager, - private val serverLogRepository: ServerLogRepository, -) : SccServerLogger { - override fun record(payload: ServerLogPayload) = transactionManager.doInTransaction { - val serverLog = ServerLog( - id = EntityIdGenerator.generateRandom(), - type = payload.type, - payload = payload, - createdAt = SccClock.instant(), - ) - - serverLogRepository.save(serverLog) - Unit - } -} diff --git a/app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/out/persistence/ServerLogRepository.kt b/app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/out/persistence/ServerLogRepository.kt deleted file mode 100644 index f51c06595..000000000 --- a/app-server/subprojects/cross_cutting_concern/application/server_log/src/main/kotlin/club/staircrusher/application/server_log/port/out/persistence/ServerLogRepository.kt +++ /dev/null @@ -1,7 +0,0 @@ -package club.staircrusher.application.server_log.port.out.persistence - -import club.staircrusher.domain.server_log.ServerLog - -interface ServerLogRepository { - fun save(entity: ServerLog): ServerLog -} diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_log/build.gradle.kts b/app-server/subprojects/cross_cutting_concern/domain/server_event/build.gradle.kts similarity index 100% rename from app-server/subprojects/cross_cutting_concern/domain/server_log/build.gradle.kts rename to app-server/subprojects/cross_cutting_concern/domain/server_event/build.gradle.kts diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/NewsletterSubscribedOnSignupPayload.kt b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/NewsletterSubscribedOnSignupPayload.kt new file mode 100644 index 000000000..df1cc7686 --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/NewsletterSubscribedOnSignupPayload.kt @@ -0,0 +1,7 @@ +package club.staircrusher.domain.server_event + +data class NewsletterSubscribedOnSignupPayload( + val userId: String, +) : ServerEventPayload { + override val type = ServerEventType.NEWSLETTER_SUBSCRIBED_ON_SIGN_UP +} diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEvent.kt b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEvent.kt new file mode 100644 index 000000000..5ba4361fb --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEvent.kt @@ -0,0 +1,10 @@ +package club.staircrusher.domain.server_event + +import java.time.Instant + +data class ServerEvent( + val id: String, + val type: ServerEventType, + val payload: ServerEventPayload, + val createdAt: Instant, +) diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventPayload.kt b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventPayload.kt new file mode 100644 index 000000000..0464fba4c --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventPayload.kt @@ -0,0 +1,5 @@ +package club.staircrusher.domain.server_event + +interface ServerEventPayload { + val type: ServerEventType +} diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventType.kt b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventType.kt new file mode 100644 index 000000000..e33522378 --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventType.kt @@ -0,0 +1,5 @@ +package club.staircrusher.domain.server_event + +enum class ServerEventType { + NEWSLETTER_SUBSCRIBED_ON_SIGN_UP, +} diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/NewsletterSubscribedOnSignupPayload.kt b/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/NewsletterSubscribedOnSignupPayload.kt deleted file mode 100644 index 2d88324a1..000000000 --- a/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/NewsletterSubscribedOnSignupPayload.kt +++ /dev/null @@ -1,7 +0,0 @@ -package club.staircrusher.domain.server_log - -data class NewsletterSubscribedOnSignupPayload( - val userId: String, -) : ServerLogPayload { - override val type = ServerLogType.NEWSLETTER_SUBSCRIBED_ON_SIGN_UP -} diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLog.kt b/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLog.kt deleted file mode 100644 index c14237c82..000000000 --- a/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLog.kt +++ /dev/null @@ -1,10 +0,0 @@ -package club.staircrusher.domain.server_log - -import java.time.Instant - -data class ServerLog( - val id: String, - val type: ServerLogType, - val payload: ServerLogPayload, - val createdAt: Instant, -) diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLogPayload.kt b/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLogPayload.kt deleted file mode 100644 index 252a0acf6..000000000 --- a/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLogPayload.kt +++ /dev/null @@ -1,5 +0,0 @@ -package club.staircrusher.domain.server_log - -interface ServerLogPayload { - val type: ServerLogType -} diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLogType.kt b/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLogType.kt deleted file mode 100644 index d8629a10a..000000000 --- a/app-server/subprojects/cross_cutting_concern/domain/server_log/src/main/kotlin/club/staircrusher/domain/server_log/ServerLogType.kt +++ /dev/null @@ -1,5 +0,0 @@ -package club.staircrusher.domain.server_log - -enum class ServerLogType { - NEWSLETTER_SUBSCRIBED_ON_SIGN_UP, -} diff --git a/app-server/subprojects/cross_cutting_concern/infra/persistence_model/build.gradle.kts b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/build.gradle.kts index 446f05711..26dce4cc2 100644 --- a/app-server/subprojects/cross_cutting_concern/infra/persistence_model/build.gradle.kts +++ b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/build.gradle.kts @@ -9,7 +9,7 @@ dependencies { implementation(projects.boundedContext.challenge.domain) implementation(projects.boundedContext.quest.domain) implementation(projects.boundedContext.user.domain) - implementation(projects.crossCuttingConcern.domain.serverLog) + implementation(projects.crossCuttingConcern.domain.serverEvent) val sqlDelightVersion: String by project api("app.cash.sqldelight:runtime-jvm:$sqlDelightVersion") diff --git a/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/kotlin/club/staircrusher/infra/persistence/sqldelight/DB.kt b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/kotlin/club/staircrusher/infra/persistence/sqldelight/DB.kt index 40e609013..83d3bafe2 100644 --- a/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/kotlin/club/staircrusher/infra/persistence/sqldelight/DB.kt +++ b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/kotlin/club/staircrusher/infra/persistence/sqldelight/DB.kt @@ -2,8 +2,8 @@ package club.staircrusher.infra.persistence.sqldelight import app.cash.sqldelight.ColumnAdapter import club.staircrusher.challenge.domain.model.ChallengeCondition -import club.staircrusher.domain.server_log.ServerLogPayload -import club.staircrusher.domain.server_log.ServerLogType +import club.staircrusher.domain.server_event.ServerEventPayload +import club.staircrusher.domain.server_event.ServerEventType import club.staircrusher.infra.persistence.sqldelight.column_adapter.AccessibilityImageListStringColumnAdapter import club.staircrusher.infra.persistence.sqldelight.column_adapter.ClubQuestPurposeTypeStringColumnAdapter import club.staircrusher.infra.persistence.sqldelight.column_adapter.EntranceDoorTypeListStringColumnAdapter @@ -22,7 +22,7 @@ import club.staircrusher.infra.persistence.sqldelight.migration.Club_quest import club.staircrusher.infra.persistence.sqldelight.migration.Place import club.staircrusher.infra.persistence.sqldelight.migration.Place_accessibility import club.staircrusher.infra.persistence.sqldelight.migration.Scc_user -import club.staircrusher.infra.persistence.sqldelight.migration.Server_log +import club.staircrusher.infra.persistence.sqldelight.migration.Server_event import club.staircrusher.infra.persistence.sqldelight.migration.User_auth_info import club.staircrusher.stdlib.di.annotation.Component import club.staircrusher.stdlib.persistence.Transaction @@ -84,22 +84,22 @@ class DB(dataSource: DataSource) : TransactionManager { club_questAdapter = Club_quest.Adapter( purpose_typeAdapter = ClubQuestPurposeTypeStringColumnAdapter, ), - server_logAdapter = Server_log.Adapter( - typeAdapter = object : ColumnAdapter { - override fun decode(databaseValue: String): ServerLogType { - return ServerLogType.valueOf(databaseValue) + server_eventAdapter = Server_event.Adapter( + typeAdapter = object : ColumnAdapter { + override fun decode(databaseValue: String): ServerEventType { + return ServerEventType.valueOf(databaseValue) } - override fun encode(value: ServerLogType): String { + override fun encode(value: ServerEventType): String { return value.name } }, - payloadAdapter = object : ColumnAdapter { - override fun decode(databaseValue: String): ServerLogPayload { + payloadAdapter = object : ColumnAdapter { + override fun decode(databaseValue: String): ServerEventPayload { return objectMapper.readValue(databaseValue) } - override fun encode(value: ServerLogPayload): String { + override fun encode(value: ServerEventPayload): String { return objectMapper.writeValueAsString(value) } } @@ -126,7 +126,7 @@ class DB(dataSource: DataSource) : TransactionManager { val challengeContributionQueries = scc.challengeContributionQueries val challengeParticipationQueries = scc.challengeParticipationQueries val challengeRankQueries = scc.challengeRankQueries - val serverLogQueries = scc.serverLogQueries + val serverEventQueries = scc.serverEventQueries override fun doInTransaction(block: Transaction.() -> T): T { diff --git a/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/migration/V26__add_server_event.sqm b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/migration/V26__add_server_event.sqm new file mode 100644 index 000000000..b334a6312 --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/migration/V26__add_server_event.sqm @@ -0,0 +1,13 @@ +import club.staircrusher.domain.server_event.ServerEventPayload; +import club.staircrusher.domain.server_event.ServerEventType; + + +CREATE TABLE IF NOT EXISTS server_event ( + id VARCHAR(36) NOT NULL, + type VARCHAR(64) AS ServerEventType NOT NULL, + payload TEXT AS ServerEventPayload NOT NULL DEFAULT '', + created_at TIMESTAMP(6) WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (id) +); + +CREATE INDEX idx_server_event_1 ON server_event(type, created_at); diff --git a/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/migration/V26__add_server_log.sqm b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/migration/V26__add_server_log.sqm deleted file mode 100644 index 6850486ad..000000000 --- a/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/migration/V26__add_server_log.sqm +++ /dev/null @@ -1,12 +0,0 @@ -import club.staircrusher.domain.server_log.ServerLogPayload; -import club.staircrusher.domain.server_log.ServerLogType; - -CREATE TABLE IF NOT EXISTS server_log ( - id VARCHAR(36) NOT NULL, - type VARCHAR(64) AS ServerLogType NOT NULL, - payload TEXT AS ServerLogPayload NOT NULL DEFAULT '', - created_at TIMESTAMP(6) WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (id) -); - -CREATE INDEX idx_server_log_1 ON server_log(type, created_at); diff --git a/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/query/server_log/ServerLog.sq b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/query/server_event/ServerEvent.sq similarity index 77% rename from app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/query/server_log/ServerLog.sq rename to app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/query/server_event/ServerEvent.sq index 9041ded9f..93805d5f4 100644 --- a/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/query/server_log/ServerLog.sq +++ b/app-server/subprojects/cross_cutting_concern/infra/persistence_model/src/main/sqldelight/club/staircrusher/infra/persistence/sqldelight/query/server_event/ServerEvent.sq @@ -1,6 +1,6 @@ save: -INSERT INTO server_log -VALUES :server_log +INSERT INTO server_event +VALUES :server_event ON CONFLICT(id) DO UPDATE SET id = EXCLUDED.id, type = EXCLUDED.type, diff --git a/app-server/subprojects/cross_cutting_concern/infra/server_log/build.gradle.kts b/app-server/subprojects/cross_cutting_concern/infra/server_event/build.gradle.kts similarity index 72% rename from app-server/subprojects/cross_cutting_concern/infra/server_log/build.gradle.kts rename to app-server/subprojects/cross_cutting_concern/infra/server_event/build.gradle.kts index ce05752da..d22bfec30 100644 --- a/app-server/subprojects/cross_cutting_concern/infra/server_log/build.gradle.kts +++ b/app-server/subprojects/cross_cutting_concern/infra/server_event/build.gradle.kts @@ -1,6 +1,6 @@ dependencies { implementation(projects.crossCuttingConcern.stdlib) implementation(projects.crossCuttingConcern.infra.persistenceModel) - api(rootProject.projects.crossCuttingConcern.domain.serverLog) - api(rootProject.projects.crossCuttingConcern.application.serverLog) + api(rootProject.projects.crossCuttingConcern.domain.serverEvent) + api(rootProject.projects.crossCuttingConcern.application.serverEvent) } diff --git a/app-server/subprojects/cross_cutting_concern/infra/server_event/src/main/kotlin/club/staircrusher/infra/server_event/out/persistence/ServerEventRepository.kt b/app-server/subprojects/cross_cutting_concern/infra/server_event/src/main/kotlin/club/staircrusher/infra/server_event/out/persistence/ServerEventRepository.kt new file mode 100644 index 000000000..0d946f5f7 --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/infra/server_event/src/main/kotlin/club/staircrusher/infra/server_event/out/persistence/ServerEventRepository.kt @@ -0,0 +1,19 @@ +package club.staircrusher.infra.server_event.out.persistence + +import club.staircrusher.application.server_event.port.out.persistence.ServerEventRepository +import club.staircrusher.domain.server_event.ServerEvent +import club.staircrusher.infra.persistence.sqldelight.DB +import club.staircrusher.infra.server_event.out.persistence.sqldelight.toPersistenceModel +import club.staircrusher.stdlib.di.annotation.Component + +@Component +class ServerEventRepository( + db: DB, +) : ServerEventRepository { + private val queries = db.serverEventQueries + + override fun save(entity: ServerEvent): ServerEvent { + queries.save(entity.toPersistenceModel()) + return entity + } +} diff --git a/app-server/subprojects/cross_cutting_concern/infra/server_log/src/main/kotlin/club/staircrusher/infra/server_log/out/persistence/sqldelight/Converters.kt b/app-server/subprojects/cross_cutting_concern/infra/server_event/src/main/kotlin/club/staircrusher/infra/server_event/out/persistence/sqldelight/Converters.kt similarity index 56% rename from app-server/subprojects/cross_cutting_concern/infra/server_log/src/main/kotlin/club/staircrusher/infra/server_log/out/persistence/sqldelight/Converters.kt rename to app-server/subprojects/cross_cutting_concern/infra/server_event/src/main/kotlin/club/staircrusher/infra/server_event/out/persistence/sqldelight/Converters.kt index c3309f3c4..caee34184 100644 --- a/app-server/subprojects/cross_cutting_concern/infra/server_log/src/main/kotlin/club/staircrusher/infra/server_log/out/persistence/sqldelight/Converters.kt +++ b/app-server/subprojects/cross_cutting_concern/infra/server_event/src/main/kotlin/club/staircrusher/infra/server_event/out/persistence/sqldelight/Converters.kt @@ -1,17 +1,17 @@ -package club.staircrusher.infra.server_log.out.persistence.sqldelight +package club.staircrusher.infra.server_event.out.persistence.sqldelight -import club.staircrusher.domain.server_log.ServerLog -import club.staircrusher.infra.persistence.sqldelight.migration.Server_log +import club.staircrusher.domain.server_event.ServerEvent +import club.staircrusher.infra.persistence.sqldelight.migration.Server_event import club.staircrusher.stdlib.time.toOffsetDateTime -fun ServerLog.toPersistenceModel() = Server_log( +fun ServerEvent.toPersistenceModel() = Server_event( id = id, type = type, payload = payload, created_at = createdAt.toOffsetDateTime(), ) -fun Server_log.toDomainModel() = ServerLog( +fun Server_event.toDomainModel() = ServerEvent( id = id, type = type, payload = payload, diff --git a/app-server/subprojects/cross_cutting_concern/infra/server_log/src/main/kotlin/club/staircrusher/infra/server_log/out/persistence/ServerLogRepository.kt b/app-server/subprojects/cross_cutting_concern/infra/server_log/src/main/kotlin/club/staircrusher/infra/server_log/out/persistence/ServerLogRepository.kt deleted file mode 100644 index 18bcb7d89..000000000 --- a/app-server/subprojects/cross_cutting_concern/infra/server_log/src/main/kotlin/club/staircrusher/infra/server_log/out/persistence/ServerLogRepository.kt +++ /dev/null @@ -1,19 +0,0 @@ -package club.staircrusher.infra.server_log.out.persistence - -import club.staircrusher.application.server_log.port.out.persistence.ServerLogRepository -import club.staircrusher.domain.server_log.ServerLog -import club.staircrusher.infra.persistence.sqldelight.DB -import club.staircrusher.infra.server_log.out.persistence.sqldelight.toPersistenceModel -import club.staircrusher.stdlib.di.annotation.Component - -@Component -class ServerLogRepository( - db: DB, -) : ServerLogRepository { - private val queries = db.serverLogQueries - - override fun save(entity: ServerLog): ServerLog { - queries.save(entity.toPersistenceModel()) - return entity - } -} diff --git a/app-server/subprojects/cross_cutting_concern/infra/spring_web/build.gradle.kts b/app-server/subprojects/cross_cutting_concern/infra/spring_web/build.gradle.kts index d9da6b741..fce420442 100644 --- a/app-server/subprojects/cross_cutting_concern/infra/spring_web/build.gradle.kts +++ b/app-server/subprojects/cross_cutting_concern/infra/spring_web/build.gradle.kts @@ -18,5 +18,5 @@ dependencies { implementation("com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonModuleKotlinVersion") integrationTestImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonModuleKotlinVersion") integrationTestImplementation("org.springframework.boot:spring-boot-starter-test") - integrationTestImplementation(projects.crossCuttingConcern.application.serverLog) + integrationTestImplementation(projects.crossCuttingConcern.application.serverEvent) } diff --git a/app-server/subprojects/cross_cutting_concern/infra/spring_web/src/integrationTest/kotlin/club/staircrusher/spring_web/mock/MockServerEventRepository.kt b/app-server/subprojects/cross_cutting_concern/infra/spring_web/src/integrationTest/kotlin/club/staircrusher/spring_web/mock/MockServerEventRepository.kt new file mode 100644 index 000000000..5815683df --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/infra/spring_web/src/integrationTest/kotlin/club/staircrusher/spring_web/mock/MockServerEventRepository.kt @@ -0,0 +1,17 @@ +package club.staircrusher.spring_web.mock + +import club.staircrusher.application.server_event.port.out.persistence.ServerEventRepository +import club.staircrusher.domain.server_event.ServerEvent +import club.staircrusher.stdlib.di.annotation.Component + +@Component +class MockServerEventRepository : ServerEventRepository { + override fun save(entity: ServerEvent): ServerEvent { + return ServerEvent( + id = entity.id, + type = entity.type, + payload = entity.payload, + createdAt = entity.createdAt + ) + } +} diff --git a/app-server/subprojects/cross_cutting_concern/infra/spring_web/src/integrationTest/kotlin/club/staircrusher/spring_web/mock/MockServerLogRepository.kt b/app-server/subprojects/cross_cutting_concern/infra/spring_web/src/integrationTest/kotlin/club/staircrusher/spring_web/mock/MockServerLogRepository.kt deleted file mode 100644 index 664b5ee88..000000000 --- a/app-server/subprojects/cross_cutting_concern/infra/spring_web/src/integrationTest/kotlin/club/staircrusher/spring_web/mock/MockServerLogRepository.kt +++ /dev/null @@ -1,17 +0,0 @@ -package club.staircrusher.spring_web.mock - -import club.staircrusher.application.server_log.port.out.persistence.ServerLogRepository -import club.staircrusher.domain.server_log.ServerLog -import club.staircrusher.stdlib.di.annotation.Component - -@Component -class MockServerLogRepository : ServerLogRepository { - override fun save(entity: ServerLog): ServerLog { - return ServerLog( - id = entity.id, - type = entity.type, - payload = entity.payload, - createdAt = entity.createdAt - ) - } -} From 4291255298e812d65abce1cd58551cff7a695b25 Mon Sep 17 00:00:00 2001 From: Jason Yoo Date: Wed, 17 Jul 2024 18:06:54 +0900 Subject: [PATCH 6/9] feat: check payload type and event type --- .../in/SccServerPersistentEventRecorder.kt | 2 +- .../domain/server_event/build.gradle.kts | 4 +++ .../NewsletterSubscribedOnSignupPayload.kt | 2 +- .../domain/server_event/ServerEvent.kt | 6 +++- .../domain/server_event/ServerEventPayload.kt | 2 +- .../domain/server_event/ServerEventType.kt | 3 ++ .../domain/server_event/ServerEventTest.kt | 32 +++++++++++++++++++ 7 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 app-server/subprojects/cross_cutting_concern/domain/server_event/src/unitTest/kotlin/club/staircrusher/domain/server_event/ServerEventTest.kt diff --git a/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerPersistentEventRecorder.kt b/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerPersistentEventRecorder.kt index a96a2f575..6ed4b8ebc 100644 --- a/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerPersistentEventRecorder.kt +++ b/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerPersistentEventRecorder.kt @@ -16,7 +16,7 @@ class SccServerPersistentEventRecorder( override fun record(payload: ServerEventPayload) = transactionManager.doInTransaction { val serverEvent = ServerEvent( id = EntityIdGenerator.generateRandom(), - type = payload.type, + type = payload.getType(), payload = payload, createdAt = SccClock.instant(), ) diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_event/build.gradle.kts b/app-server/subprojects/cross_cutting_concern/domain/server_event/build.gradle.kts index 2fcbb0129..19aa57066 100644 --- a/app-server/subprojects/cross_cutting_concern/domain/server_event/build.gradle.kts +++ b/app-server/subprojects/cross_cutting_concern/domain/server_event/build.gradle.kts @@ -1,4 +1,8 @@ dependencies { val kotlinxSerializationVersion: String by project implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinxSerializationVersion") + + val jUnitJupiterVersion: String by project + testImplementation("org.junit.jupiter:junit-jupiter-api:$jUnitJupiterVersion") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$jUnitJupiterVersion") } diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/NewsletterSubscribedOnSignupPayload.kt b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/NewsletterSubscribedOnSignupPayload.kt index df1cc7686..2c9d38042 100644 --- a/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/NewsletterSubscribedOnSignupPayload.kt +++ b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/NewsletterSubscribedOnSignupPayload.kt @@ -3,5 +3,5 @@ package club.staircrusher.domain.server_event data class NewsletterSubscribedOnSignupPayload( val userId: String, ) : ServerEventPayload { - override val type = ServerEventType.NEWSLETTER_SUBSCRIBED_ON_SIGN_UP + override fun getType() = ServerEventType.NEWSLETTER_SUBSCRIBED_ON_SIGN_UP } diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEvent.kt b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEvent.kt index 5ba4361fb..2d65a6742 100644 --- a/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEvent.kt +++ b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEvent.kt @@ -7,4 +7,8 @@ data class ServerEvent( val type: ServerEventType, val payload: ServerEventPayload, val createdAt: Instant, -) +) { + init { + check(type == payload.getType()) + } +} diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventPayload.kt b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventPayload.kt index 0464fba4c..126b9f653 100644 --- a/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventPayload.kt +++ b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventPayload.kt @@ -1,5 +1,5 @@ package club.staircrusher.domain.server_event interface ServerEventPayload { - val type: ServerEventType + fun getType(): ServerEventType } diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventType.kt b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventType.kt index e33522378..ec9089391 100644 --- a/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventType.kt +++ b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventType.kt @@ -2,4 +2,7 @@ package club.staircrusher.domain.server_event enum class ServerEventType { NEWSLETTER_SUBSCRIBED_ON_SIGN_UP, + // For test + // TODO: event type 이 더 생기면 테스트 코드 변경하고 삭제하기 + UNKNOWN, } diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_event/src/unitTest/kotlin/club/staircrusher/domain/server_event/ServerEventTest.kt b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/unitTest/kotlin/club/staircrusher/domain/server_event/ServerEventTest.kt new file mode 100644 index 000000000..bbf5a87ff --- /dev/null +++ b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/unitTest/kotlin/club/staircrusher/domain/server_event/ServerEventTest.kt @@ -0,0 +1,32 @@ +package club.staircrusher.domain.server_event + +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertDoesNotThrow +import org.junit.jupiter.api.assertThrows +import java.time.Instant + +class ServerEventTest { + + @Test + fun `ServerEvent 의 type 과 주어진 payload 의 type 이 일치해야 한다`() { + val serverEventPayload = NewsletterSubscribedOnSignupPayload("example") + + assertDoesNotThrow { + ServerEvent( + id = "example", + type = ServerEventType.NEWSLETTER_SUBSCRIBED_ON_SIGN_UP, + payload = serverEventPayload, + createdAt = Instant.now(), + ) + } + + assertThrows { + ServerEvent( + id = "example", + type = ServerEventType.UNKNOWN, + payload = serverEventPayload, + createdAt = Instant.now(), + ) + } + } +} From f675ffecd01bdebaf18539db7f34f5f8e9b66dbd Mon Sep 17 00:00:00 2001 From: Jason Yoo Date: Wed, 17 Jul 2024 23:27:53 +0900 Subject: [PATCH 7/9] refactor: function -> val --- .../domain/server_event/NewsletterSubscribedOnSignupPayload.kt | 2 +- .../kotlin/club/staircrusher/domain/server_event/ServerEvent.kt | 2 +- .../club/staircrusher/domain/server_event/ServerEventPayload.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/NewsletterSubscribedOnSignupPayload.kt b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/NewsletterSubscribedOnSignupPayload.kt index 2c9d38042..df1cc7686 100644 --- a/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/NewsletterSubscribedOnSignupPayload.kt +++ b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/NewsletterSubscribedOnSignupPayload.kt @@ -3,5 +3,5 @@ package club.staircrusher.domain.server_event data class NewsletterSubscribedOnSignupPayload( val userId: String, ) : ServerEventPayload { - override fun getType() = ServerEventType.NEWSLETTER_SUBSCRIBED_ON_SIGN_UP + override val type = ServerEventType.NEWSLETTER_SUBSCRIBED_ON_SIGN_UP } diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEvent.kt b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEvent.kt index 2d65a6742..027a02ded 100644 --- a/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEvent.kt +++ b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEvent.kt @@ -9,6 +9,6 @@ data class ServerEvent( val createdAt: Instant, ) { init { - check(type == payload.getType()) + check(type == payload.type) } } diff --git a/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventPayload.kt b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventPayload.kt index 126b9f653..0464fba4c 100644 --- a/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventPayload.kt +++ b/app-server/subprojects/cross_cutting_concern/domain/server_event/src/main/kotlin/club/staircrusher/domain/server_event/ServerEventPayload.kt @@ -1,5 +1,5 @@ package club.staircrusher.domain.server_event interface ServerEventPayload { - fun getType(): ServerEventType + val type: ServerEventType } From 2b5e39bceb07a880f6ef5f26a96b8d565aba3e04 Mon Sep 17 00:00:00 2001 From: Jason Yoo Date: Wed, 17 Jul 2024 23:30:34 +0900 Subject: [PATCH 8/9] fix: build --- .../server_event/port/in/SccServerPersistentEventRecorder.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerPersistentEventRecorder.kt b/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerPersistentEventRecorder.kt index 6ed4b8ebc..a96a2f575 100644 --- a/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerPersistentEventRecorder.kt +++ b/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerPersistentEventRecorder.kt @@ -16,7 +16,7 @@ class SccServerPersistentEventRecorder( override fun record(payload: ServerEventPayload) = transactionManager.doInTransaction { val serverEvent = ServerEvent( id = EntityIdGenerator.generateRandom(), - type = payload.getType(), + type = payload.type, payload = payload, createdAt = SccClock.instant(), ) From 6a9b16cc0ba49aaaea25d2d0675eef45a2dc0ce3 Mon Sep 17 00:00:00 2001 From: Jason Yoo Date: Wed, 17 Jul 2024 23:34:31 +0900 Subject: [PATCH 9/9] chore: try and catch --- .../in/SccServerPersistentEventRecorder.kt | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerPersistentEventRecorder.kt b/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerPersistentEventRecorder.kt index a96a2f575..290786835 100644 --- a/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerPersistentEventRecorder.kt +++ b/app-server/subprojects/cross_cutting_concern/application/server_event/src/main/kotlin/club/staircrusher/application/server_event/port/in/SccServerPersistentEventRecorder.kt @@ -7,21 +7,29 @@ import club.staircrusher.stdlib.clock.SccClock import club.staircrusher.stdlib.di.annotation.Component import club.staircrusher.stdlib.domain.entity.EntityIdGenerator import club.staircrusher.stdlib.persistence.TransactionManager +import mu.KotlinLogging @Component class SccServerPersistentEventRecorder( private val transactionManager: TransactionManager, private val serverEventRepository: ServerEventRepository, ) : SccServerEventRecorder { + private val logger = KotlinLogging.logger { } + override fun record(payload: ServerEventPayload) = transactionManager.doInTransaction { - val serverEvent = ServerEvent( - id = EntityIdGenerator.generateRandom(), - type = payload.type, - payload = payload, - createdAt = SccClock.instant(), - ) + val serverEvent = try { + ServerEvent( + id = EntityIdGenerator.generateRandom(), + type = payload.type, + payload = payload, + createdAt = SccClock.instant(), + ) + } catch (e: Exception){ + logger.error(e) { "Failed to create server event of payload: $payload" } + null + } - serverEventRepository.save(serverEvent) + serverEvent?.let { serverEventRepository.save(it) } Unit } }