Skip to content

Commit

Permalink
Move MailState into the value module
Browse files Browse the repository at this point in the history
  • Loading branch information
awelless committed Feb 17, 2024
1 parent 971f810 commit a69deca
Show file tree
Hide file tree
Showing 26 changed files with 298 additions and 270 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class MailMessageResource(
createdAt = createdAt,
sendingStartedAt = sendingStartedAt,
sentAt = sentAt,
status = status,
status = state,
failedCount = failedCount,
)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.mailit.admin.console.http.dto

import io.mailit.core.model.MailMessageStatus
import io.mailit.value.MailState
import io.quarkus.runtime.annotations.RegisterForReflection
import java.time.Instant

Expand All @@ -13,6 +13,6 @@ data class AdminSlicedMailDto(
val createdAt: Instant,
val sendingStartedAt: Instant?,
val sentAt: Instant?,
val status: MailMessageStatus,
val status: MailState, // todo: rename to "state"
val failedCount: Int,
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package io.mailit.test

import io.mailit.core.model.HtmlMailMessageType
import io.mailit.core.model.MailMessage
import io.mailit.core.model.MailMessageStatus
import io.mailit.core.model.MailMessageTemplate
import io.mailit.core.model.MailMessageType
import io.mailit.core.model.PlainTextMailMessageType
import io.mailit.value.EmailAddress.Companion.toEmailAddress
import io.mailit.value.MailId
import io.mailit.value.MailState
import io.mailit.value.MailTypeId
import io.mailit.value.TemplateEngine
import java.util.concurrent.atomic.AtomicLong
Expand Down Expand Up @@ -54,7 +54,7 @@ fun createMailMessage(messageType: MailMessageType): MailMessage {
emailTo = "email@to.com".toEmailAddress(),
type = messageType,
createdAt = nowWithoutNanos(),
status = MailMessageStatus.PENDING,
state = MailState.PENDING,
deduplicationId = id.toString(),
)
}
36 changes: 2 additions & 34 deletions core/model/src/main/kotlin/io/mailit/core/model/MailMessage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.mailit.core.model

import io.mailit.value.EmailAddress
import io.mailit.value.MailId
import io.mailit.value.MailState
import java.time.Instant

data class MailMessage(
Expand Down Expand Up @@ -35,7 +36,7 @@ data class MailMessage(

var sentAt: Instant? = null,

var status: MailMessageStatus,
var state: MailState,

var failedCount: Int = 0,

Expand All @@ -45,36 +46,3 @@ data class MailMessage(
*/
val deduplicationId: String?,
)

enum class MailMessageStatus {

/**
* Just created. Available for sending.
*/
PENDING,

/**
* Sending failed one or several times, but can be retried. Available for sending.
*/
RETRY,

/**
* Message is being sent right now.
*/
SENDING,

/**
* Message has been sent successfully.
*/
SENT,

/**
* Message sending failed and all available retries failed.
*/
FAILED,

/**
* Message sending was canceled (e.g. [MailMessageType] had been force deleted).
*/
CANCELED,
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import io.mailit.core.exception.ValidationException
import io.mailit.core.external.api.CreateMailRequest
import io.mailit.core.external.api.MailMessageService as ConnectorMailMessageService
import io.mailit.core.model.MailMessage
import io.mailit.core.model.MailMessageStatus
import io.mailit.core.model.Slice
import io.mailit.core.spi.MailMessageRepository
import io.mailit.core.spi.MailMessageTypeRepository
import io.mailit.idgenerator.api.IdGenerator
import io.mailit.value.MailId
import io.mailit.value.MailState
import java.time.Instant
import mu.KLogging

Expand All @@ -37,7 +37,7 @@ class MailMessageServiceImpl(
emailTo = command.emailTo,
type = messageType,
createdAt = Instant.now(),
status = MailMessageStatus.PENDING,
state = MailState.PENDING,
deduplicationId = command.deduplicationId,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ package io.mailit.core.service.mail.sending

import io.mailit.core.exception.NotFoundException
import io.mailit.core.model.MailMessage
import io.mailit.core.model.MailMessageStatus.CANCELED
import io.mailit.core.model.MailMessageStatus.FAILED
import io.mailit.core.model.MailMessageStatus.PENDING
import io.mailit.core.model.MailMessageStatus.RETRY
import io.mailit.core.model.MailMessageStatus.SENDING
import io.mailit.core.model.MailMessageStatus.SENT
import io.mailit.core.spi.MailMessageRepository
import io.mailit.value.MailId
import io.mailit.value.MailState.CANCELED
import io.mailit.value.MailState.FAILED
import io.mailit.value.MailState.PENDING
import io.mailit.value.MailState.RETRY
import io.mailit.value.MailState.SENDING
import io.mailit.value.MailState.SENT
import java.time.Clock
import kotlin.time.Duration.Companion.minutes
import kotlin.time.toJavaDuration
Expand All @@ -21,22 +21,22 @@ class MailMessageService(
) {
companion object : KLogging()

private val hungMessageStatuses = listOf(SENDING)
private val hungMessageStates = listOf(SENDING)
private val hungMessageDuration = 2.minutes.toJavaDuration()

private val possibleToSendMessageStatuses = listOf(PENDING, RETRY)
private val possibleToSendMessageStates = listOf(PENDING, RETRY)

suspend fun getHungMessages(maxListSize: Int) =
mailMessageRepository.findAllWithTypeByStatusesAndSendingStartedBefore(hungMessageStatuses, clock.instant().minus(hungMessageDuration), maxListSize)
mailMessageRepository.findAllWithTypeByStatesAndSendingStartedBefore(hungMessageStates, clock.instant().minus(hungMessageDuration), maxListSize)

suspend fun getAllIdsOfPossibleToSentMessages(maxListSize: Int) =
mailMessageRepository.findAllIdsByStatusIn(possibleToSendMessageStatuses, maxListSize)
mailMessageRepository.findAllIdsByStateIn(possibleToSendMessageStates, maxListSize)

suspend fun getMessageForSending(messageId: MailId): MailMessage {
val messagesUpdated = mailMessageRepository.updateMessageStatusAndSendingStartedTimeByIdAndStatusIn(
val messagesUpdated = mailMessageRepository.updateMessageStateAndSendingStartedTimeByIdAndStateIn(
id = messageId,
statuses = possibleToSendMessageStatuses,
status = SENDING,
states = possibleToSendMessageStates,
state = SENDING,
sendingStartedAt = clock.instant(),
)

Expand All @@ -50,35 +50,35 @@ class MailMessageService(

suspend fun processSuccessfulDelivery(mailMessage: MailMessage) {
mailMessage.apply {
status = SENT
state = SENT
sentAt = clock.instant()
}

mailMessageRepository.updateMessageStatusAndSentTime(mailMessage.id, mailMessage.status, mailMessage.sentAt!!)
mailMessageRepository.updateMessageStateAndSentTime(mailMessage.id, mailMessage.state, mailMessage.sentAt!!)
}

suspend fun processFailedDelivery(mailMessage: MailMessage) {
mailMessage.apply {
val maxRetries = type.maxRetriesCount ?: Int.MAX_VALUE

if (failedCount >= maxRetries) {
status = FAILED
state = FAILED
logger.error { "Max number of retries exceeded. Marking MailMessage: $id as failed" }
} else {
failedCount++
status = RETRY
state = RETRY
logger.info { "Failed MailMessage: $id is scheduled for another delivery" }
}

sendingStartedAt = null
}

mailMessageRepository.updateMessageStatusFailedCountAndSendingStartedTime(mailMessage.id, mailMessage.status, mailMessage.failedCount, null)
mailMessageRepository.updateMessageStateFailedCountAndSendingStartedTime(mailMessage.id, mailMessage.state, mailMessage.failedCount, null)
}

suspend fun processMessageTypeForceDeletion(mailMessage: MailMessage) {
mailMessage.status = CANCELED
mailMessage.state = CANCELED

mailMessageRepository.updateMessageStatus(mailMessage.id, mailMessage.status)
mailMessageRepository.updateMessageState(mailMessage.id, mailMessage.state)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import io.mailit.core.exception.DuplicateUniqueKeyException
import io.mailit.core.exception.ValidationException
import io.mailit.core.external.api.CreateMailRequest
import io.mailit.core.model.MailMessage
import io.mailit.core.model.MailMessageStatus.PENDING
import io.mailit.core.model.MailMessageType
import io.mailit.core.spi.MailMessageRepository
import io.mailit.core.spi.MailMessageTypeRepository
Expand All @@ -13,6 +12,7 @@ import io.mailit.test.createMailMessage
import io.mailit.test.createPlainMailMessageType
import io.mailit.value.EmailAddress.Companion.toEmailAddress
import io.mailit.value.MailId
import io.mailit.value.MailState.PENDING
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.impl.annotations.InjectMockKs
Expand Down Expand Up @@ -83,7 +83,7 @@ class MailMessageServiceImplTest {
assertEquals(command.emailFrom, savedMailMessage.emailFrom)
assertEquals(command.emailTo, savedMailMessage.emailTo)
assertEquals(mailType, savedMailMessage.type)
assertEquals(PENDING, savedMailMessage.status)
assertEquals(PENDING, savedMailMessage.state)
assertEquals(command.deduplicationId, savedMailMessage.deduplicationId)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ package io.mailit.core.service.mail.sending

import io.mailit.core.exception.NotFoundException
import io.mailit.core.model.MailMessage
import io.mailit.core.model.MailMessageStatus.FAILED
import io.mailit.core.model.MailMessageStatus.PENDING
import io.mailit.core.model.MailMessageStatus.RETRY
import io.mailit.core.model.MailMessageStatus.SENDING
import io.mailit.core.model.MailMessageStatus.SENT
import io.mailit.core.model.MailMessageType
import io.mailit.core.spi.MailMessageRepository
import io.mailit.test.createMailMessage
import io.mailit.test.createPlainMailMessageType
import io.mailit.value.MailState.FAILED
import io.mailit.value.MailState.PENDING
import io.mailit.value.MailState.RETRY
import io.mailit.value.MailState.SENDING
import io.mailit.value.MailState.SENT
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.impl.annotations.RelaxedMockK
Expand Down Expand Up @@ -51,10 +51,10 @@ class MailMessageServiceTest {
@Test
fun getMessageForSending_marksStatusSending() = runTest {
coEvery {
mailMessageRepository.updateMessageStatusAndSendingStartedTimeByIdAndStatusIn(
mailMessageRepository.updateMessageStateAndSendingStartedTimeByIdAndStateIn(
id = mailMessage.id,
statuses = possibleToSendMessageStatuses,
status = SENDING,
states = possibleToSendMessageStatuses,
state = SENDING,
sendingStartedAt = frozenNow,
)
}.returns(1)
Expand All @@ -68,10 +68,10 @@ class MailMessageServiceTest {
@Test
fun getMessageForSending_notFoundForMarking_marksStatusSending() = runTest {
coEvery {
mailMessageRepository.updateMessageStatusAndSendingStartedTimeByIdAndStatusIn(
mailMessageRepository.updateMessageStateAndSendingStartedTimeByIdAndStateIn(
id = mailMessage.id,
statuses = possibleToSendMessageStatuses,
status = SENDING,
states = possibleToSendMessageStatuses,
state = SENDING,
sendingStartedAt = frozenNow,
)
}.returns(0)
Expand All @@ -83,7 +83,7 @@ class MailMessageServiceTest {
fun processSuccessfulDelivery_marksStatusSent() = runTest {
mailMessageService.processSuccessfulDelivery(mailMessage)

coVerify { mailMessageRepository.updateMessageStatusAndSentTime(mailMessage.id, SENT, frozenNow) }
coVerify { mailMessageRepository.updateMessageStateAndSentTime(mailMessage.id, SENT, frozenNow) }
}

@Test
Expand All @@ -92,7 +92,7 @@ class MailMessageServiceTest {

mailMessageService.processFailedDelivery(mailMessage)

coVerify { mailMessageRepository.updateMessageStatusFailedCountAndSendingStartedTime(mailMessage.id, RETRY, 1, null) }
coVerify { mailMessageRepository.updateMessageStateFailedCountAndSendingStartedTime(mailMessage.id, RETRY, 1, null) }
}

@Test
Expand All @@ -102,6 +102,6 @@ class MailMessageServiceTest {

mailMessageService.processFailedDelivery(mailMessage)

coVerify { mailMessageRepository.updateMessageStatusFailedCountAndSendingStartedTime(mailMessage.id, FAILED, 10, null) }
coVerify { mailMessageRepository.updateMessageStateFailedCountAndSendingStartedTime(mailMessage.id, FAILED, 10, null) }
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
package io.mailit.core.spi

import io.mailit.core.model.MailMessage
import io.mailit.core.model.MailMessageStatus
import io.mailit.core.model.Slice
import io.mailit.value.MailId
import io.mailit.value.MailState
import java.time.Instant

interface MailMessageRepository {

suspend fun findOneWithTypeById(id: MailId): MailMessage?

suspend fun findAllWithTypeByStatusesAndSendingStartedBefore(
statuses: Collection<MailMessageStatus>,
suspend fun findAllWithTypeByStatesAndSendingStartedBefore(
states: Collection<MailState>,
sendingStartedBefore: Instant,
maxListSize: Int,
): List<MailMessage>

suspend fun findAllIdsByStatusIn(statuses: Collection<MailMessageStatus>, maxListSize: Int): List<MailId>
suspend fun findAllIdsByStateIn(states: Collection<MailState>, maxListSize: Int): List<MailId>

/**
* Returns a [Slice] of specified zero indexed [page] and [size]
Expand All @@ -25,16 +25,16 @@ interface MailMessageRepository {

suspend fun create(mailMessage: MailMessage): MailMessage

suspend fun updateMessageStatus(id: MailId, status: MailMessageStatus): Int
suspend fun updateMessageState(id: MailId, state: MailState): Int

suspend fun updateMessageStatusAndSendingStartedTimeByIdAndStatusIn(
suspend fun updateMessageStateAndSendingStartedTimeByIdAndStateIn(
id: MailId,
statuses: Collection<MailMessageStatus>,
status: MailMessageStatus,
states: Collection<MailState>,
state: MailState,
sendingStartedAt: Instant,
): Int

suspend fun updateMessageStatusAndSentTime(id: MailId, status: MailMessageStatus, sentAt: Instant): Int
suspend fun updateMessageStateAndSentTime(id: MailId, state: MailState, sentAt: Instant): Int

suspend fun updateMessageStatusFailedCountAndSendingStartedTime(id: MailId, status: MailMessageStatus, failedCount: Int, sendingStartedAt: Instant?): Int
suspend fun updateMessageStateFailedCountAndSendingStartedTime(id: MailId, state: MailState, failedCount: Int, sendingStartedAt: Instant?): Int
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,15 @@ class MailMessageResourceTest {
"content[0].emailTo" equalTo mail2.emailTo.email,
"content[0].type.id" equalTo mail2.type.id.toString(),
"content[0].type.name" equalTo mail2.type.name,
"content[0].status" equalTo mail2.status.name,
"content[0].status" equalTo mail2.state.name,
"content[0].failedCount" equalTo mail2.failedCount,

"content[1].id" equalTo mail1.id.value.toString(),
"content[1].emailFrom" equalTo mail1.emailFrom?.email,
"content[1].emailTo" equalTo mail1.emailTo.email,
"content[1].type.id" equalTo mail1.type.id.toString(),
"content[1].type.name" equalTo mail1.type.name,
"content[1].status" equalTo mail1.status.name,
"content[1].status" equalTo mail1.state.name,
"content[1].failedCount" equalTo mail1.failedCount,

"last" equalTo true,
Expand Down
Loading

0 comments on commit a69deca

Please sign in to comment.