Skip to content

Commit

Permalink
release v1.1.11
Browse files Browse the repository at this point in the history
  • Loading branch information
DongGeon0908 committed Aug 19, 2024
2 parents a1d2192 + 4061c92 commit 9d1edc0
Show file tree
Hide file tree
Showing 13 changed files with 192 additions and 19 deletions.
2 changes: 1 addition & 1 deletion api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ tasks.getByName("bootJar") {
}

tasks.getByName("jar") {
enabled = false
enabled = true
}

springBoot.buildInfo { properties { } }
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.oksusu.susu.api.event.listener

import com.oksusu.susu.api.auth.application.AuthFacade
import com.oksusu.susu.api.auth.model.AuthUser
import com.oksusu.susu.api.auth.model.AuthUserToken
import com.oksusu.susu.api.common.aspect.SusuEventListener
import com.oksusu.susu.api.event.model.SystemActionLogEvent
import com.oksusu.susu.api.log.application.SystemActionLogService
Expand All @@ -9,27 +12,37 @@ import com.oksusu.susu.domain.log.domain.SystemActionLog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.reactor.awaitSingleOrNull
import org.springframework.context.event.EventListener
import reactor.kotlin.core.publisher.toMono

@SusuEventListener
class SystemActionLogEventListener(
private val systemActionLogService: SystemActionLogService,
private val coroutineExceptionHandler: ErrorPublishingCoroutineExceptionHandler,
private val authFacade: AuthFacade,
) {
@EventListener
fun subscribe(event: SystemActionLogEvent) {
if (check(event)) {
return
}

mdcCoroutineScope(Dispatchers.IO + Job() + coroutineExceptionHandler.handler, event.traceId).launch {
if (check(event)) {
SystemActionLog(
ipAddress = event.ipAddress,
path = event.path,
httpMethod = event.method,
userAgent = event.userAgent,
host = event.host,
referer = event.referer,
extra = event.extra
).run { systemActionLogService.record(this) }
}
val authUser = event.token
?.let { token -> AuthUserToken.from(token).toMono() }
?.let { token -> authFacade.resolveAuthUser(token).awaitSingleOrNull() as? AuthUser }

SystemActionLog(
uid = authUser?.uid,
ipAddress = event.ipAddress,
path = event.path,
httpMethod = event.method,
userAgent = event.userAgent,
host = event.host,
referer = event.referer,
extra = event.extra
).run { systemActionLogService.record(this) }
}
}

Expand Down
3 changes: 3 additions & 0 deletions api/src/main/kotlin/com/oksusu/susu/api/event/model/Event.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.oksusu.susu.api.event.model

import com.oksusu.susu.api.auth.model.AUTH_TOKEN_KEY
import com.oksusu.susu.api.auth.model.AuthUser
import com.oksusu.susu.api.extension.remoteIp
import com.oksusu.susu.cache.model.OidcPublicKeysCacheModel
Expand Down Expand Up @@ -49,6 +50,7 @@ data class SystemActionLogEvent(
val userAgent: String?,
val host: String?,
val referer: String?,
val token: String?,
val extra: String?,
) : BaseEvent() {
companion object {
Expand All @@ -66,6 +68,7 @@ data class SystemActionLogEvent(
userAgent = request.headers[USER_AGENT].toString(),
host = request.headers[HOST].toString(),
referer = request.headers[REFERER].toString(),
token = request.headers[AUTH_TOKEN_KEY].toString(),
extra = mapper.writeValueAsString(request.headers)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import io.kotest.matchers.equals.shouldBeEqual
import io.mockk.every
import io.mockk.mockk
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.delay

class BoardServiceTest : DescribeSpec({
val logger = KotlinLogging.logger { }
Expand All @@ -25,6 +26,8 @@ class BoardServiceTest : DescribeSpec({

beforeSpec {
boardService.refreshBoards()

delay(100)
}

describe("scheduler") {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package com.oksusu.susu.batch.discord.job

import com.oksusu.susu.cache.key.Cache
import com.oksusu.susu.cache.model.FailedSentDiscordMessageCache
import com.oksusu.susu.cache.service.CacheService
import com.oksusu.susu.client.discord.DiscordClient
import com.oksusu.susu.client.discord.model.DiscordMessageModel
import io.github.oshai.kotlinlogging.KotlinLogging
import kotlinx.coroutines.*
import org.springframework.stereotype.Component
import java.time.LocalDateTime

@Component
class ResendFailedSentDiscordMessageJob(
private val cacheService: CacheService,
private val discordClient: DiscordClient,
) {
private val logger = KotlinLogging.logger { }

companion object {
private const val RESEND_BEFORE_MINUTES = 1L
}

suspend fun resendFailedSentDiscordMessage() {
logger.info { "start resend failed sent discord message" }

// 1분 전에 실패한 것이 타겟 (현재가 24분이면 23분을 말하는 것)
val targetTime = LocalDateTime.now().minusMinutes(RESEND_BEFORE_MINUTES)

// 실패 메세지 조회 및 삭제
val failedMessages = withContext(Dispatchers.IO) {
cacheService.sGetMembers(Cache.getFailedSentDiscordMessageCache(targetTime))
}

withContext(Dispatchers.IO) {
cacheService.sDelete(Cache.getFailedSentDiscordMessageCache(targetTime))
}

// 다수 메세지 token 별로 하나의 메세지로 병합
val message = mergeFailedMessage(failedMessages)

// 재전송
runCatching {
coroutineScope {
val sendDeferreds = message.map { (token, message) ->
val discordMessageModel = DiscordMessageModel(content = message)

async(Dispatchers.IO) {
discordClient.sendMessage(
message = discordMessageModel,
token = token,
withRecover = false
)
}
}.toTypedArray()

awaitAll(*sendDeferreds)
}
}.onFailure {
// 재전송 실패시 1분 뒤에 다시 보낼 수 있게, 1분 뒤에 보내는 메세지 목록에 추가
logger.warn { "postpone resend discord message" }

postponeResendTimeOfFailedMessage(targetTime, message)
}

logger.info { "finish resend failed sent discord message" }
}

private suspend fun mergeFailedMessage(failedMessages: List<FailedSentDiscordMessageCache>): Map<String, String> {
val message = mutableMapOf<String, String>()

failedMessages.forEach { model ->
val recoverMsg = if (model.isStacked) {
model.message
} else {
"[RECOVER - ${model.failedAt} discord failure] ${model.message}"
}

val stackedMessage = message[model.token]

message[model.token] = if (stackedMessage == null) {
recoverMsg
} else {
"$stackedMessage\n$recoverMsg"
}
}

return message
}

private suspend fun postponeResendTimeOfFailedMessage(targetTime: LocalDateTime, message: Map<String, String>) {
val nextTime = targetTime.plusMinutes(RESEND_BEFORE_MINUTES)

coroutineScope {
message.map { (token, message) ->
val model = FailedSentDiscordMessageCache(
token = token,
message = message,
isStacked = true
)

async(Dispatchers.IO) {
cacheService.sSet(
cache = Cache.getFailedSentDiscordMessageCache(nextTime),
value = model
)
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.oksusu.susu.batch.discord.scheduler

import com.oksusu.susu.batch.discord.job.ResendFailedSentDiscordMessageJob
import com.oksusu.susu.batch.slack.job.ResendFailedSentSlackMessageJob
import com.oksusu.susu.client.common.coroutine.ErrorPublishingCoroutineExceptionHandler
import com.oksusu.susu.common.extension.isProd
import com.oksusu.susu.common.extension.resolveCancellation
import io.github.oshai.kotlinlogging.KotlinLogging
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.springframework.core.env.Environment
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Component

@Component
class ResendFailedSentDiscordMessageScheduler(
private val environment: Environment,
private val resendFailedSentDiscordMessageJob: ResendFailedSentDiscordMessageJob,
private val coroutineExceptionHandler: ErrorPublishingCoroutineExceptionHandler,
) {
private val logger = KotlinLogging.logger { }

@Scheduled(
fixedRate = 1000 * 60,
initialDelayString = "\${oksusu.scheduled-tasks.resend-failed-sent-discord-message.initial-delay:100}"
)
fun resendFailedSentDiscordMessageJob() {
if (environment.isProd()) {
CoroutineScope(Dispatchers.IO + coroutineExceptionHandler.handler).launch {
runCatching {
resendFailedSentDiscordMessageJob.resendFailedSentDiscordMessage()
}.onFailure { e ->
logger.resolveCancellation("[BATCH] fail to run resendFailedSentDiscordMessageJob", e)
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
package com.oksusu.susu.domain.log.domain

import com.oksusu.susu.domain.common.BaseEntity
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.GeneratedValue
import jakarta.persistence.GenerationType
import jakarta.persistence.Id
import jakarta.persistence.Table
import jakarta.persistence.*

@Entity
@Table(name = "system_action_log")
Expand All @@ -15,6 +10,9 @@ class SystemActionLog(
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long = -1L,

@Column(name = "uid")
val uid: Long? = null,

@Column(name = "ip_address")
val ipAddress: String? = null,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import java.time.LocalDateTime

@Transactional(readOnly = true)
interface ReportHistoryQRepository {
@Transactional
fun updateAllCreatedAt(createdAt: LocalDateTime): Long
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import java.time.LocalDateTime

@Transactional(readOnly = true)
interface ReportResultQRepository {
@Transactional
fun updateAllCreatedAt(createdAt: LocalDateTime): Long
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ interface UserStatusHistoryQRepository {

fun getUidByToStatusId(toStatusId: Long): List<Long>

@Transactional
fun updateAllCreatedAt(createdAt: LocalDateTime): Long
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import java.time.LocalDateTime

@Transactional(readOnly = true)
interface UserStatusQRepository {
@Transactional
fun updateAllCreatedAt(createdAt: LocalDateTime): Long
}

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
version=1.1.10
version=1.1.11
kotlin.code.style=official
2 changes: 2 additions & 0 deletions sql/ddl/log/DDL.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
CREATE TABLE `system_action_log`
(
`id` bigint NOT NULL AUTO_INCREMENT,
`uid` int DEFAULT NULL COMMENT 'uid',
`host` varchar(255) DEFAULT NULL,
`http_method` varchar(255) DEFAULT NULL,
`ip_address` varchar(255) DEFAULT NULL,
Expand All @@ -14,3 +15,4 @@ CREATE TABLE `system_action_log`
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT 'system log';
CREATE INDEX idx__created_at ON system_action_log (created_at);
CREATE INDEX idx__uid ON system_action_log (uid);

0 comments on commit 9d1edc0

Please sign in to comment.