Skip to content

Commit

Permalink
Feat(Chat): 채팅 메시지 저장 관련 로직 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
waterfogSW committed Dec 30, 2024
1 parent d9b4143 commit 022b430
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package com.threedays.application.chat.service
import com.threedays.application.chat.port.inbound.ReceiveMessage
import com.threedays.application.chat.port.outbound.SessionClient
import com.threedays.domain.chat.entity.Channel
import com.threedays.domain.chat.entity.Message
import com.threedays.domain.chat.entity.Session
import com.threedays.domain.chat.repository.ChannelRepository
import com.threedays.domain.chat.repository.MessageRepository
import com.threedays.domain.chat.repository.SessionRepository
import io.github.oshai.kotlinlogging.KotlinLogging
import kotlinx.coroutines.CoroutineExceptionHandler
Expand All @@ -17,6 +19,7 @@ import org.springframework.stereotype.Service
class ReceiveMessageService(
private val sessionClient: SessionClient,
private val channelRepository: ChannelRepository,
private val messageRepository: MessageRepository,
private val sessionRepository: SessionRepository,
) : ReceiveMessage {

Expand All @@ -32,12 +35,22 @@ class ReceiveMessageService(
private val scope = CoroutineScope(Dispatchers.IO + exceptionHandler)

override fun invoke(command: ReceiveMessage.Command) {
val channel: Channel = channelRepository.findById(command.message.channelId) ?: return
val message = command.message
saveMessage(message)
broadcastMessage(message)
}

private fun saveMessage(message: Message) {
messageRepository.save(message)
}

private fun broadcastMessage(message: Message) {
val channel: Channel = channelRepository.findById(message.channelId) ?: return
val sessions: List<Session> = channel.getMemberSessions(sessionRepository)

sessions.forEach { session ->
scope.launch {
sessionClient.sendMessage(session, command.message)
sessionClient.sendMessage(session, message)
}
}
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.threedays.persistence.chat.adapter

import com.threedays.domain.chat.entity.Message
import com.threedays.domain.chat.repository.MessageRepository
import com.threedays.persistence.chat.entity.MessageJpaEntity
import com.threedays.persistence.chat.repository.MessageJpaRepository
import org.springframework.stereotype.Repository

@Repository
class MessagePersistenceAdapter(
private val messageJpaRepository: MessageJpaRepository,
) : MessageRepository {

override fun save(message: Message) {
val messageJpaEntity: MessageJpaEntity = MessageJpaEntity.from(message)
messageJpaRepository.save(messageJpaEntity)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package com.threedays.persistence.chat.entity

import com.threedays.domain.chat.entity.Channel
import com.threedays.domain.chat.entity.Message
import com.threedays.domain.user.entity.User
import jakarta.persistence.*
import java.time.LocalDateTime
import java.util.*

@Entity
@Table(name = "messages")
class MessageJpaEntity(
id: UUID,
channelId: UUID,
senderUserId: UUID,
content: String,
contentType: ContentType,
cardColor: Message.Content.Card.Color?,
status: Message.Status,
createdAt: LocalDateTime,
updatedAt: LocalDateTime?,
) {
@Id
var id: UUID = id
private set

@Column(name = "channel_id", nullable = false)
var channelId: UUID = channelId
private set

@Column(name = "sender_user_id", nullable = false)
var senderUserId: UUID = senderUserId
private set

@Column(name = "content", nullable = false, columnDefinition = "TEXT")
var content: String = content
private set

@Enumerated(EnumType.STRING)
@Column(name = "content_type", nullable = false)
var contentType: ContentType = contentType
private set

@Enumerated(EnumType.STRING)
@Column(name = "card_color")
var cardColor: Message.Content.Card.Color? = cardColor
private set

@Enumerated(EnumType.STRING)
@Column(name = "status", nullable = false)
var status: Message.Status = status
private set

@Column(name = "created_at", nullable = false)
var createdAt: LocalDateTime = createdAt
private set

@Column(name = "updated_at")
var updatedAt: LocalDateTime? = updatedAt
private set

enum class ContentType {
TEXT, CARD
}

fun toDomain(): Message {
val messageContent = when (contentType) {
ContentType.TEXT -> Message.Content.Text(content)
ContentType.CARD -> Message.Content.Card(
text = content,
color = cardColor!!
)
}

return Message(
id = Message.Id(id),
channelId = Channel.Id(channelId),
senderUserId = User.Id(senderUserId),
content = messageContent,
status = status,
createdAt = createdAt,
updatedAt = updatedAt
)
}

companion object {
fun from(message: Message): MessageJpaEntity {
val (contentType, content, cardColor) = when (val messageContent = message.content) {
is Message.Content.Text -> Triple(ContentType.TEXT, messageContent.text, null)
is Message.Content.Card -> Triple(
ContentType.CARD,
messageContent.text,
messageContent.color
)
}

return MessageJpaEntity(
id = message.id.value,
channelId = message.channelId.value,
senderUserId = message.senderUserId.value,
content = content,
contentType = contentType,
cardColor = cardColor,
status = message.status,
createdAt = message.createdAt,
updatedAt = message.updatedAt
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.threedays.persistence.chat.repository

import com.threedays.persistence.chat.entity.MessageJpaEntity
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
import java.util.*

@Repository
interface MessageJpaRepository : JpaRepository<MessageJpaEntity, UUID>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
CREATE TABLE messages
(
id BINARY(16) NOT NULL COMMENT '메시지 ID',
channel_id BINARY(16) NOT NULL COMMENT '채널 ID',
sender_user_id BINARY(16) NOT NULL COMMENT '발신자 사용자 ID',
content TEXT NOT NULL COMMENT '메시지 내용',
content_type VARCHAR(10) NOT NULL COMMENT '메시지 타입 (TEXT, CARD)',
card_color VARCHAR(10) COMMENT '카드 색상 (BLUE, PINK)',
status VARCHAR(10) NOT NULL COMMENT '메시지 상태 (SENT, READ)',
created_at DATETIME(6) NOT NULL COMMENT '생성일시',
updated_at DATETIME(6) COMMENT '수정일시',
PRIMARY KEY (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_unicode_ci COMMENT ='채팅 메시지';

CREATE INDEX idx_messages_channel_id ON messages (channel_id);
CREATE INDEX idx_messages_sender_user_id ON messages (sender_user_id);

0 comments on commit 022b430

Please sign in to comment.