From 13eab715a33930812ab43912ecca56082466e04b Mon Sep 17 00:00:00 2001 From: DongGeon0908 Date: Sun, 18 Aug 2024 21:11:39 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EA=B7=B9=EB=9D=BD=20=ED=86=B5=EA=B3=84?= =?UTF-8?q?=20=EC=95=8C=EB=A6=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{ => posecount}/job/PoseCountUpdateJob.kt | 2 +- .../scheduler/PoseCountScheduler.kt | 4 +- .../batch/statistics/job/HeroStatisticsJob.kt | 89 +++++++++++++++++++ .../scheduler/HeroStatisticsScheduler.kt | 43 +++++++++ .../client/discord/DiscordWebhookService.kt | 18 ++++ .../discord/client/DiscordWebhookClient.kt | 4 +- .../client/SuspendableDiscordWebhookClient.kt | 4 +- .../dev/resource/DevDiscordWebhookResource.kt | 17 +++- .../infrastructure/DiscussionRepository.kt | 5 +- .../group/infrastructure/GroupRepository.kt | 3 + .../infrastructure/GroupUserRepository.kt | 3 + .../infrastructure/ImageMetadataRepository.kt | 5 +- .../SystemActionLogRepository.kt | 5 +- .../PoseNotificationRepository.kt | 3 + .../infrastructure/PoseSnapshotRepository.kt | 5 +- .../CredentialUserInfoRepository.kt | 3 + .../infrastructure/OAuthUserInfoRepository.kt | 3 + .../user/infrastructure/UserInfoRepository.kt | 5 +- 18 files changed, 207 insertions(+), 14 deletions(-) rename src/main/kotlin/com/hero/alignlab/batch/{ => posecount}/job/PoseCountUpdateJob.kt (98%) rename src/main/kotlin/com/hero/alignlab/batch/{ => posecount}/scheduler/PoseCountScheduler.kt (90%) create mode 100644 src/main/kotlin/com/hero/alignlab/batch/statistics/job/HeroStatisticsJob.kt create mode 100644 src/main/kotlin/com/hero/alignlab/batch/statistics/scheduler/HeroStatisticsScheduler.kt create mode 100644 src/main/kotlin/com/hero/alignlab/client/discord/DiscordWebhookService.kt diff --git a/src/main/kotlin/com/hero/alignlab/batch/job/PoseCountUpdateJob.kt b/src/main/kotlin/com/hero/alignlab/batch/posecount/job/PoseCountUpdateJob.kt similarity index 98% rename from src/main/kotlin/com/hero/alignlab/batch/job/PoseCountUpdateJob.kt rename to src/main/kotlin/com/hero/alignlab/batch/posecount/job/PoseCountUpdateJob.kt index c06463b..7b21234 100644 --- a/src/main/kotlin/com/hero/alignlab/batch/job/PoseCountUpdateJob.kt +++ b/src/main/kotlin/com/hero/alignlab/batch/posecount/job/PoseCountUpdateJob.kt @@ -1,4 +1,4 @@ -package com.hero.alignlab.batch.job +package com.hero.alignlab.batch.posecount.job import com.hero.alignlab.common.extension.executesOrNull import com.hero.alignlab.config.database.TransactionTemplates diff --git a/src/main/kotlin/com/hero/alignlab/batch/scheduler/PoseCountScheduler.kt b/src/main/kotlin/com/hero/alignlab/batch/posecount/scheduler/PoseCountScheduler.kt similarity index 90% rename from src/main/kotlin/com/hero/alignlab/batch/scheduler/PoseCountScheduler.kt rename to src/main/kotlin/com/hero/alignlab/batch/posecount/scheduler/PoseCountScheduler.kt index cf746c2..6e2b1ce 100644 --- a/src/main/kotlin/com/hero/alignlab/batch/scheduler/PoseCountScheduler.kt +++ b/src/main/kotlin/com/hero/alignlab/batch/posecount/scheduler/PoseCountScheduler.kt @@ -1,6 +1,6 @@ -package com.hero.alignlab.batch.scheduler +package com.hero.alignlab.batch.posecount.scheduler -import com.hero.alignlab.batch.job.PoseCountUpdateJob +import com.hero.alignlab.batch.posecount.job.PoseCountUpdateJob import com.hero.alignlab.common.extension.CoroutineExtension.retryOnError import com.hero.alignlab.common.extension.resolveCancellation import io.github.oshai.kotlinlogging.KotlinLogging diff --git a/src/main/kotlin/com/hero/alignlab/batch/statistics/job/HeroStatisticsJob.kt b/src/main/kotlin/com/hero/alignlab/batch/statistics/job/HeroStatisticsJob.kt new file mode 100644 index 0000000..f0891f1 --- /dev/null +++ b/src/main/kotlin/com/hero/alignlab/batch/statistics/job/HeroStatisticsJob.kt @@ -0,0 +1,89 @@ +package com.hero.alignlab.batch.statistics.job + +import com.hero.alignlab.client.discord.DiscordWebhookService +import com.hero.alignlab.client.discord.model.request.SendMessageRequest +import com.hero.alignlab.domain.discussion.infrastructure.DiscussionRepository +import com.hero.alignlab.domain.group.infrastructure.GroupRepository +import com.hero.alignlab.domain.group.infrastructure.GroupUserRepository +import com.hero.alignlab.domain.log.infrastructure.SystemActionLogRepository +import com.hero.alignlab.domain.notification.infrastructure.PoseNotificationRepository +import com.hero.alignlab.domain.pose.infrastructure.PoseSnapshotRepository +import com.hero.alignlab.domain.user.infrastructure.CredentialUserInfoRepository +import com.hero.alignlab.domain.user.infrastructure.OAuthUserInfoRepository +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.coroutineScope +import org.springframework.stereotype.Component +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter + +@Component +class HeroStatisticsJob( + private val discordWebhookService: DiscordWebhookService, + + /** repository */ + private val groupRepository: GroupRepository, + private val groupUserRepository: GroupUserRepository, + private val discussionRepository: DiscussionRepository, + private val imageRepository: GroupRepository, + private val systemActionLogRepository: SystemActionLogRepository, + private val poseNotificationRepository: PoseNotificationRepository, + private val poseSnapshotRepository: PoseSnapshotRepository, + private val credentialUserInfoRepository: CredentialUserInfoRepository, + private val oAuthUserInfoRepository: OAuthUserInfoRepository, + private val userInfoRepository: CredentialUserInfoRepository, +) { + suspend fun sendHeroStatistics(title: String, fromDate: LocalDateTime, toDate: LocalDateTime) { + coroutineScope { + val groupCount = async(Dispatchers.IO) { + groupRepository.countByCreatedAtBetween(fromDate, toDate) + }.await() + val groupUserCount = async(Dispatchers.IO) { + groupUserRepository.countByCreatedAtBetween(fromDate, toDate) + }.await() + val discussionCount = async(Dispatchers.IO) { + discussionRepository.countByCreatedAtBetween(fromDate, toDate) + }.await() + val syslogCount = async(Dispatchers.IO) { + systemActionLogRepository.countByCreatedAtBetween(fromDate, toDate) + }.await() + val poseNotificationCount = async(Dispatchers.IO) { + poseNotificationRepository.countByCreatedAtBetween(fromDate, toDate) + }.await() + val poseSnapshotCount = async(Dispatchers.IO) { + poseSnapshotRepository.countByCreatedAtBetween(fromDate, toDate) + }.await() + val credentialUserInfoCount = async(Dispatchers.IO) { + credentialUserInfoRepository.countByCreatedAtBetween(fromDate, toDate) + }.await() + val oAuthUserInfoCount = async(Dispatchers.IO) { + oAuthUserInfoRepository.countByCreatedAtBetween(fromDate, toDate) + }.await() + val userInfoCount = async(Dispatchers.IO) { + userInfoRepository.countByCreatedAtBetween(fromDate, toDate) + }.await() + val imageCount = async(Dispatchers.IO) { + imageRepository.countByCreatedAtBetween(fromDate, toDate) + }.await() + + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") + + val message = """ + $title + - targetDate: ${fromDate.format(formatter)} ~ ${toDate.format(formatter)} + - 그룹 생성수 : $groupCount + - 그룹 유저 생성수 : $groupUserCount + - 문의하기 생성수 : $discussionCount + - api 호출량 : $syslogCount + - 포즈 알림 설정수 : $poseNotificationCount + - 포즈 스냅샷 생성수 : $poseSnapshotCount + - 일반 회원가입수 : $credentialUserInfoCount + - OAuth 회원가입수 : $oAuthUserInfoCount + - 유저 생성수 : $userInfoCount + - 이미지 생성수 : $imageCount + """.trimIndent() + + discordWebhookService.sendMessage(SendMessageRequest(message)) + } + } +} diff --git a/src/main/kotlin/com/hero/alignlab/batch/statistics/scheduler/HeroStatisticsScheduler.kt b/src/main/kotlin/com/hero/alignlab/batch/statistics/scheduler/HeroStatisticsScheduler.kt new file mode 100644 index 0000000..cc3da5a --- /dev/null +++ b/src/main/kotlin/com/hero/alignlab/batch/statistics/scheduler/HeroStatisticsScheduler.kt @@ -0,0 +1,43 @@ +package com.hero.alignlab.batch.statistics.scheduler + +import com.hero.alignlab.batch.statistics.job.HeroStatisticsJob +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import org.springframework.scheduling.annotation.Scheduled +import org.springframework.stereotype.Component +import java.time.LocalDateTime + +@Component +class HeroStatisticsScheduler( + private val heroStatisticsJob: HeroStatisticsJob +) { + @Scheduled(cron = "0 0 0/1 * * *") + fun dailyRunJob() { + CoroutineScope(Dispatchers.IO + Job()).launch { + val toDate = LocalDateTime.now() + val fromDate = LocalDateTime.now().minusHours(1) + + heroStatisticsJob.sendHeroStatistics( + title = "극락통계 1시간 단위 [$fromDate ~ $toDate]", + fromDate = fromDate, + toDate = toDate + ) + } + } + + @Scheduled(cron = "0 0 9 * * *") + fun runDailySummary() { + CoroutineScope(Dispatchers.IO + Job()).launch { + val toDate = LocalDateTime.now() + val fromDate = LocalDateTime.now().minusDays(1) + + heroStatisticsJob.sendHeroStatistics( + title = "극락통계 1일 단위 [$fromDate ~ $toDate]", + fromDate = fromDate, + toDate = toDate + ) + } + } +} diff --git a/src/main/kotlin/com/hero/alignlab/client/discord/DiscordWebhookService.kt b/src/main/kotlin/com/hero/alignlab/client/discord/DiscordWebhookService.kt new file mode 100644 index 0000000..7fcef44 --- /dev/null +++ b/src/main/kotlin/com/hero/alignlab/client/discord/DiscordWebhookService.kt @@ -0,0 +1,18 @@ +package com.hero.alignlab.client.discord + +import com.hero.alignlab.client.discord.client.DiscordWebhookClient +import com.hero.alignlab.client.discord.model.request.SendMessageRequest +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import org.springframework.stereotype.Service + +@Service +class DiscordWebhookService( + private val discordWebhookClient: DiscordWebhookClient, +) { + suspend fun sendMessage(request: SendMessageRequest) { + withContext(Dispatchers.IO) { + discordWebhookClient.sendMessage(request) + } + } +} diff --git a/src/main/kotlin/com/hero/alignlab/client/discord/client/DiscordWebhookClient.kt b/src/main/kotlin/com/hero/alignlab/client/discord/client/DiscordWebhookClient.kt index 7b7ea73..701822d 100644 --- a/src/main/kotlin/com/hero/alignlab/client/discord/client/DiscordWebhookClient.kt +++ b/src/main/kotlin/com/hero/alignlab/client/discord/client/DiscordWebhookClient.kt @@ -4,7 +4,7 @@ import com.hero.alignlab.client.discord.model.request.SendMessageRequest import com.hero.alignlab.client.discord.model.response.GetWebhookWithTokenResponse interface DiscordWebhookClient { - suspend fun getWebhookWithToken(id: Int): GetWebhookWithTokenResponse + suspend fun getWebhookWithToken(): GetWebhookWithTokenResponse - suspend fun sendMessage(id: Int, request: SendMessageRequest) + suspend fun sendMessage(request: SendMessageRequest) } diff --git a/src/main/kotlin/com/hero/alignlab/client/discord/client/SuspendableDiscordWebhookClient.kt b/src/main/kotlin/com/hero/alignlab/client/discord/client/SuspendableDiscordWebhookClient.kt index 708b809..a1dc625 100644 --- a/src/main/kotlin/com/hero/alignlab/client/discord/client/SuspendableDiscordWebhookClient.kt +++ b/src/main/kotlin/com/hero/alignlab/client/discord/client/SuspendableDiscordWebhookClient.kt @@ -8,13 +8,13 @@ import org.springframework.web.reactive.function.client.WebClient class SuspendableDiscordWebhookClient( client: WebClient, ) : DiscordWebhookClient, SuspendableClient(client) { - override suspend fun getWebhookWithToken(id: Int): GetWebhookWithTokenResponse { + override suspend fun getWebhookWithToken(): GetWebhookWithTokenResponse { return client .get() .request() } - override suspend fun sendMessage(id: Int, request: SendMessageRequest) { + override suspend fun sendMessage(request: SendMessageRequest) { return client .post() .bodyValue(request) diff --git a/src/main/kotlin/com/hero/alignlab/domain/dev/resource/DevDiscordWebhookResource.kt b/src/main/kotlin/com/hero/alignlab/domain/dev/resource/DevDiscordWebhookResource.kt index cc44d0d..ae8319c 100644 --- a/src/main/kotlin/com/hero/alignlab/domain/dev/resource/DevDiscordWebhookResource.kt +++ b/src/main/kotlin/com/hero/alignlab/domain/dev/resource/DevDiscordWebhookResource.kt @@ -1,5 +1,6 @@ package com.hero.alignlab.domain.dev.resource +import com.hero.alignlab.batch.statistics.job.HeroStatisticsJob import com.hero.alignlab.client.discord.client.DiscordWebhookClient import com.hero.alignlab.client.discord.model.request.SendMessageRequest import com.hero.alignlab.config.dev.DevResourceCheckConfig.Companion.devResource @@ -8,20 +9,32 @@ import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag import org.springframework.http.MediaType import org.springframework.web.bind.annotation.* +import java.time.LocalDateTime @Tag(name = DEV_TAG) @RestController @RequestMapping(produces = [MediaType.APPLICATION_JSON_VALUE]) class DevDiscordWebhookResource( private val discordWebhookClient: DiscordWebhookClient, + private val statisticsJob: HeroStatisticsJob, ) { @Operation(summary = "discord webhook test") @PostMapping("/api/dev/v1/discord-webhooks/{id}") suspend fun sendMessage( - @PathVariable id: Int, @RequestHeader("X-HERO-DEV-TOKEN") token: String, @RequestParam message: String, ) = devResource(token) { - discordWebhookClient.sendMessage(id, SendMessageRequest(message)) + discordWebhookClient.sendMessage(SendMessageRequest(message)) + } + + @Operation(summary = "discord webhook daily noti") + @PostMapping("/api/dev/v1/discord-webhooks/daily-noti") + suspend fun sendDailyNoti( + @RequestHeader("X-HERO-DEV-TOKEN") token: String, + ) = devResource(token) { + val toDate = LocalDateTime.now() + val fromDate = LocalDateTime.now().minusHours(1) + + statisticsJob.sendHeroStatistics("극락통계 테스트", fromDate, toDate) } } diff --git a/src/main/kotlin/com/hero/alignlab/domain/discussion/infrastructure/DiscussionRepository.kt b/src/main/kotlin/com/hero/alignlab/domain/discussion/infrastructure/DiscussionRepository.kt index b1b0fc1..2cdeaee 100644 --- a/src/main/kotlin/com/hero/alignlab/domain/discussion/infrastructure/DiscussionRepository.kt +++ b/src/main/kotlin/com/hero/alignlab/domain/discussion/infrastructure/DiscussionRepository.kt @@ -4,7 +4,10 @@ import com.hero.alignlab.domain.discussion.domain.Discussion import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository import org.springframework.transaction.annotation.Transactional +import java.time.LocalDateTime @Transactional(readOnly = true) @Repository -interface DiscussionRepository : JpaRepository +interface DiscussionRepository : JpaRepository { + fun countByCreatedAtBetween(startAt: LocalDateTime, endAt: LocalDateTime): Long +} diff --git a/src/main/kotlin/com/hero/alignlab/domain/group/infrastructure/GroupRepository.kt b/src/main/kotlin/com/hero/alignlab/domain/group/infrastructure/GroupRepository.kt index e5c460c..9a8d13d 100644 --- a/src/main/kotlin/com/hero/alignlab/domain/group/infrastructure/GroupRepository.kt +++ b/src/main/kotlin/com/hero/alignlab/domain/group/infrastructure/GroupRepository.kt @@ -4,6 +4,7 @@ import com.hero.alignlab.domain.group.domain.Group import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository import org.springframework.transaction.annotation.Transactional +import java.time.LocalDateTime @Repository @Transactional(readOnly = true) @@ -11,4 +12,6 @@ interface GroupRepository : JpaRepository { fun existsByName(name: String): Boolean fun findByIdAndOwnerUid(id: Long, ownerUid: Long): Group? + + fun countByCreatedAtBetween(startAt: LocalDateTime, endAt: LocalDateTime): Long } diff --git a/src/main/kotlin/com/hero/alignlab/domain/group/infrastructure/GroupUserRepository.kt b/src/main/kotlin/com/hero/alignlab/domain/group/infrastructure/GroupUserRepository.kt index f50d3fe..dbcf100 100644 --- a/src/main/kotlin/com/hero/alignlab/domain/group/infrastructure/GroupUserRepository.kt +++ b/src/main/kotlin/com/hero/alignlab/domain/group/infrastructure/GroupUserRepository.kt @@ -6,6 +6,7 @@ import org.springframework.data.domain.Pageable import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository import org.springframework.transaction.annotation.Transactional +import java.time.LocalDateTime @Transactional(readOnly = true) @Repository @@ -23,4 +24,6 @@ interface GroupUserRepository : JpaRepository { fun findAllByGroupId(groupId: Long, pageable: Pageable): Page fun existsByUid(uid: Long): Boolean + + fun countByCreatedAtBetween(startAt: LocalDateTime, endAt: LocalDateTime): Long } diff --git a/src/main/kotlin/com/hero/alignlab/domain/image/infrastructure/ImageMetadataRepository.kt b/src/main/kotlin/com/hero/alignlab/domain/image/infrastructure/ImageMetadataRepository.kt index 0853f4f..6d68a8f 100644 --- a/src/main/kotlin/com/hero/alignlab/domain/image/infrastructure/ImageMetadataRepository.kt +++ b/src/main/kotlin/com/hero/alignlab/domain/image/infrastructure/ImageMetadataRepository.kt @@ -4,7 +4,10 @@ import com.hero.alignlab.domain.image.domain.ImageMetadata import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository import org.springframework.transaction.annotation.Transactional +import java.time.LocalDateTime @Transactional(readOnly = true) @Repository -interface ImageMetadataRepository : JpaRepository +interface ImageMetadataRepository : JpaRepository { + fun countByCreatedAtBetween(startAt: LocalDateTime, endAt: LocalDateTime): Long +} diff --git a/src/main/kotlin/com/hero/alignlab/domain/log/infrastructure/SystemActionLogRepository.kt b/src/main/kotlin/com/hero/alignlab/domain/log/infrastructure/SystemActionLogRepository.kt index 071ef4f..a5f1f5e 100644 --- a/src/main/kotlin/com/hero/alignlab/domain/log/infrastructure/SystemActionLogRepository.kt +++ b/src/main/kotlin/com/hero/alignlab/domain/log/infrastructure/SystemActionLogRepository.kt @@ -4,7 +4,10 @@ import com.hero.alignlab.domain.log.domain.SystemActionLog import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository import org.springframework.transaction.annotation.Transactional +import java.time.LocalDateTime @Transactional(readOnly = true) @Repository -interface SystemActionLogRepository : JpaRepository +interface SystemActionLogRepository : JpaRepository { + fun countByCreatedAtBetween(startAt: LocalDateTime, endAt: LocalDateTime): Long +} diff --git a/src/main/kotlin/com/hero/alignlab/domain/notification/infrastructure/PoseNotificationRepository.kt b/src/main/kotlin/com/hero/alignlab/domain/notification/infrastructure/PoseNotificationRepository.kt index b34ffee..4a47b73 100644 --- a/src/main/kotlin/com/hero/alignlab/domain/notification/infrastructure/PoseNotificationRepository.kt +++ b/src/main/kotlin/com/hero/alignlab/domain/notification/infrastructure/PoseNotificationRepository.kt @@ -3,10 +3,13 @@ package com.hero.alignlab.domain.notification.infrastructure import com.hero.alignlab.domain.notification.domain.PoseNotification import org.springframework.data.jpa.repository.JpaRepository import org.springframework.transaction.annotation.Transactional +import java.time.LocalDateTime @Transactional(readOnly = true) interface PoseNotificationRepository : JpaRepository { fun findByUidAndIsActive(uid: Long, isActive: Boolean): PoseNotification? fun findByUid(uid: Long): PoseNotification? + + fun countByCreatedAtBetween(startAt: LocalDateTime, endAt: LocalDateTime): Long } diff --git a/src/main/kotlin/com/hero/alignlab/domain/pose/infrastructure/PoseSnapshotRepository.kt b/src/main/kotlin/com/hero/alignlab/domain/pose/infrastructure/PoseSnapshotRepository.kt index 2b40d07..65df63c 100644 --- a/src/main/kotlin/com/hero/alignlab/domain/pose/infrastructure/PoseSnapshotRepository.kt +++ b/src/main/kotlin/com/hero/alignlab/domain/pose/infrastructure/PoseSnapshotRepository.kt @@ -13,10 +13,13 @@ import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport import org.springframework.stereotype.Repository import org.springframework.transaction.annotation.Transactional import java.time.LocalDate +import java.time.LocalDateTime @Transactional(readOnly = true) @Repository -interface PoseSnapshotRepository : JpaRepository, PoseSnapshotQRepository +interface PoseSnapshotRepository : JpaRepository, PoseSnapshotQRepository { + fun countByCreatedAtBetween(startAt: LocalDateTime, endAt: LocalDateTime): Long +} @Transactional(readOnly = true) interface PoseSnapshotQRepository { diff --git a/src/main/kotlin/com/hero/alignlab/domain/user/infrastructure/CredentialUserInfoRepository.kt b/src/main/kotlin/com/hero/alignlab/domain/user/infrastructure/CredentialUserInfoRepository.kt index 384f99d..be60bb7 100644 --- a/src/main/kotlin/com/hero/alignlab/domain/user/infrastructure/CredentialUserInfoRepository.kt +++ b/src/main/kotlin/com/hero/alignlab/domain/user/infrastructure/CredentialUserInfoRepository.kt @@ -5,6 +5,7 @@ import com.hero.alignlab.domain.user.domain.CredentialUserInfo import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository import org.springframework.transaction.annotation.Transactional +import java.time.LocalDateTime @Transactional(readOnly = true) @Repository @@ -12,4 +13,6 @@ interface CredentialUserInfoRepository : JpaRepository fun existsByUsername(username: String): Boolean fun findByUsernameAndPassword(username: String, password: EncryptData): CredentialUserInfo? + + fun countByCreatedAtBetween(startAt: LocalDateTime, endAt: LocalDateTime): Long } diff --git a/src/main/kotlin/com/hero/alignlab/domain/user/infrastructure/OAuthUserInfoRepository.kt b/src/main/kotlin/com/hero/alignlab/domain/user/infrastructure/OAuthUserInfoRepository.kt index c0e9940..ce0896a 100644 --- a/src/main/kotlin/com/hero/alignlab/domain/user/infrastructure/OAuthUserInfoRepository.kt +++ b/src/main/kotlin/com/hero/alignlab/domain/user/infrastructure/OAuthUserInfoRepository.kt @@ -5,6 +5,7 @@ import com.hero.alignlab.domain.user.domain.OAuthUserInfo import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository import org.springframework.transaction.annotation.Transactional +import java.time.LocalDateTime @Transactional(readOnly = true) @Repository @@ -14,4 +15,6 @@ interface OAuthUserInfoRepository : JpaRepository { fun deleteByOauthIdAndProvider(oauthId: String, provider: OAuthProvider) fun findByProviderAndOauthId(provider: OAuthProvider, oauthId: String): OAuthUserInfo? + + fun countByCreatedAtBetween(startAt: LocalDateTime, endAt: LocalDateTime): Long } diff --git a/src/main/kotlin/com/hero/alignlab/domain/user/infrastructure/UserInfoRepository.kt b/src/main/kotlin/com/hero/alignlab/domain/user/infrastructure/UserInfoRepository.kt index ad28b13..f364034 100644 --- a/src/main/kotlin/com/hero/alignlab/domain/user/infrastructure/UserInfoRepository.kt +++ b/src/main/kotlin/com/hero/alignlab/domain/user/infrastructure/UserInfoRepository.kt @@ -10,10 +10,13 @@ import org.springframework.data.jpa.repository.JpaRepository import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport import org.springframework.stereotype.Repository import org.springframework.transaction.annotation.Transactional +import java.time.LocalDateTime @Transactional(readOnly = true) @Repository -interface UserInfoRepository : JpaRepository, UserInfoQRepository +interface UserInfoRepository : JpaRepository, UserInfoQRepository { + fun countByCreatedAtBetween(startAt: LocalDateTime, endAt: LocalDateTime): Long +} @Transactional(readOnly = true) interface UserInfoQRepository {