Skip to content

Commit

Permalink
Merge pull request #105 from soma-baekgu/develop
Browse files Browse the repository at this point in the history
운영 서버 1.2 배포
  • Loading branch information
Dltmd202 authored Aug 28, 2024
2 parents 75e3b47 + d3cf3a2 commit 4e8c84e
Show file tree
Hide file tree
Showing 78 changed files with 1,010 additions and 130 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/ci-cd-main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ jobs:
envs: APP, COMPOSE
script_stop: true
script: |
ssh api1 "aws ecr get-login-password --region ${{ env.AWS_REGION }} | docker login --username AWS --password-stdin ${{ secrets.AWS_ECR_REGISTRY }}"
ssh api1 docker-compose -f $COMPOSE down
ssh api1 docker pull ${{secrets.IMAGE_API}}
ssh api1 docker-compose -p api -f $COMPOSE up -d
Expand Down Expand Up @@ -178,6 +179,7 @@ jobs:
envs: APP, COMPOSE
script_stop: true
script: |
ssh notification1 "aws ecr get-login-password --region ${{ env.AWS_REGION }} | docker login --username AWS --password-stdin ${{ secrets.AWS_ECR_REGISTRY }}"
ssh notification1 docker-compose -f $COMPOSE down
ssh notification1 docker pull ${{secrets.IMAGE_NOTIFICATION}}
ssh notification1 docker-compose -p notification -f $COMPOSE up -d
Expand Down Expand Up @@ -264,6 +266,7 @@ jobs:
envs: APP, COMPOSE
script_stop: true
script: |
ssh batch1 "aws ecr get-login-password --region ${{ env.AWS_REGION }} | docker login --username AWS --password-stdin ${{ secrets.AWS_ECR_REGISTRY }}"
ssh batch1 docker-compose -f $COMPOSE down
ssh batch1 docker pull ${{secrets.IMAGE_BATCH}}
ssh batch1 docker-compose -p batch -f $COMPOSE up -d
Expand Down Expand Up @@ -350,6 +353,7 @@ jobs:
envs: APP, COMPOSE
script_stop: true
script: |
ssh realtime1 "aws ecr get-login-password --region ${{ env.AWS_REGION }} | docker login --username AWS --password-stdin ${{ secrets.AWS_ECR_REGISTRY }}"
ssh realtime1 docker-compose -f $COMPOSE down
ssh realtime1 docker pull ${{secrets.IMAGE_REALTIME}}
ssh realtime1 docker-compose -p realtime -f $COMPOSE up -d
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,5 @@ kafka_data

.run

/*/src/*/resources/application-test.yaml
/*/src/*/resources/application-test*.yaml
/notification/src/*/resources/firebase/*.json
2 changes: 1 addition & 1 deletion Dockerfile-api
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ FROM openjdk:17
RUN ln -snf /usr/share/zoneinfo/Asia/Seoul /etc/localtime && echo "Asia/Seoul" > /etc/timezone
ARG JAR_FILE=api/build/libs/*.jar
COPY ${JAR_FILE} /root/app.jar
CMD ["java", "-jar", "/root/app.jar"]
CMD ["java", "-Dspring.profiles.active=prod", "-jar", "/root/app.jar"]
2 changes: 1 addition & 1 deletion Dockerfile-batch
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ FROM openjdk:17
RUN ln -snf /usr/share/zoneinfo/Asia/Seoul /etc/localtime && echo "Asia/Seoul" > /etc/timezone
ARG JAR_FILE=batch/build/libs/*.jar
COPY ${JAR_FILE} /root/app.jar
CMD ["java", "-jar", "/root/app.jar"]
CMD ["java", "-Dspring.profiles.active=prod", "-jar", "/root/app.jar"]
2 changes: 1 addition & 1 deletion Dockerfile-notification
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ FROM openjdk:17
RUN ln -snf /usr/share/zoneinfo/Asia/Seoul /etc/localtime && echo "Asia/Seoul" > /etc/timezone
ARG JAR_FILE=notification/build/libs/*.jar
COPY ${JAR_FILE} /root/app.jar
CMD ["java", "-jar", "/root/app.jar"]
CMD ["java", "-Dspring.profiles.active=prod", "-jar", "/root/app.jar"]
3 changes: 1 addition & 2 deletions Dockerfile-realtime
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@ FROM openjdk:17
RUN ln -snf /usr/share/zoneinfo/Asia/Seoul /etc/localtime && echo "Asia/Seoul" > /etc/timezone
ARG JAR_FILE=realtime/build/libs/*.jar
COPY ${JAR_FILE} /root/app.jar
ENV HOST_IP=host.docker.internal
CMD ["java", "-jar", "/root/app.jar"]
CMD ["java", "-Dspring.profiles.active=prod", "-jar", "/root/app.jar"]
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import com.backgu.amaker.application.chat.service.ChatUserCacheFacadeService
import com.backgu.amaker.application.event.service.EventAssignedUserService
import com.backgu.amaker.application.user.service.UserCacheService
import com.backgu.amaker.application.user.service.UserService
import com.backgu.amaker.infra.jpa.chat.repository.ChatRepository
import com.backgu.amaker.infra.jpa.chat.query.ChatRepository
import com.backgu.amaker.infra.jpa.chat.repository.ChatRoomRepository
import com.backgu.amaker.infra.jpa.chat.repository.ChatRoomUserRepository
import com.backgu.amaker.infra.redis.chat.repository.ChatCacheRepository
import com.backgu.amaker.infra.redis.chat.repository.ChatPipelinedQueryRepository
import com.backgu.amaker.infra.redis.chat.repository.ChatRoomUserCacheRepository
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
Expand Down Expand Up @@ -43,12 +44,14 @@ class ChatServiceConfig {
fun chatUserCacheService(
chatCacheService: ChatCacheService,
userCacheService: UserCacheService,
chatPipelinedQueryRepository: ChatPipelinedQueryRepository,
chatRoomUserCacheService: ChatRoomUserCacheService,
userService: UserService,
chatService: ChatService,
eventAssignedUserService: EventAssignedUserService,
) = ChatUserCacheFacadeService(
chatCacheService,
chatPipelinedQueryRepository,
userCacheService,
chatRoomUserCacheService,
userService,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.backgu.amaker.api.user.dto.UserDto
import com.backgu.amaker.domain.chat.ChatType
import com.backgu.amaker.domain.chat.ChatWithUser
import com.backgu.amaker.domain.chat.DefaultChatWithUser
import com.backgu.amaker.domain.event.EventWithUser
import com.backgu.amaker.domain.chat.EventChatWithUser
import java.time.LocalDateTime

sealed interface ChatWithUserDto<T> {
Expand All @@ -31,11 +31,11 @@ sealed interface ChatWithUserDto<T> {
user = UserDto.of(chatWithUser.user),
)

else ->
is EventChatWithUser ->
EventChatWithUserDto(
id = chatWithUser.id,
chatRoomId = chatWithUser.chatRoomId,
content = EventWithUserDto.of(chatWithUser.content as EventWithUser),
content = EventWithUserDto.of(chatWithUser.content),
chatType = chatWithUser.chatType,
createdAt = chatWithUser.createdAt,
updatedAt = chatWithUser.updatedAt,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.backgu.amaker.api.chat.dto.response

import com.backgu.amaker.api.chat.dto.ChatWithUserDto
import com.backgu.amaker.api.chat.dto.DefaultChatWithUserDto
import com.backgu.amaker.api.chat.dto.EventChatWithUserDto
import com.backgu.amaker.api.user.dto.response.UserResponse
import com.backgu.amaker.domain.chat.ChatType
Expand Down Expand Up @@ -32,7 +33,7 @@ interface ChatWithUserResponse<T> {
fun of(chatWithUserDto: ChatWithUserDto<*>): ChatWithUserResponse<*> =
when (chatWithUserDto) {
is EventChatWithUserDto -> EventChatWithUserResponse.of(chatWithUserDto)
else -> DefaultChatWithUserResponse.of(chatWithUserDto)
is DefaultChatWithUserDto -> DefaultChatWithUserResponse.of(chatWithUserDto)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.backgu.amaker.application.chat.service.ChatService
import com.backgu.amaker.application.chat.service.ChatUserCacheFacadeService
import com.backgu.amaker.application.event.service.EventAssignedUserService
import com.backgu.amaker.application.event.service.EventService
import com.backgu.amaker.application.notification.service.NotificationEventService
import com.backgu.amaker.application.user.service.UserService
import com.backgu.amaker.common.exception.BusinessException
import com.backgu.amaker.common.status.StatusCode
Expand All @@ -25,6 +26,7 @@ import com.backgu.amaker.domain.chat.ChatType
import com.backgu.amaker.domain.chat.DefaultChatWithUser
import com.backgu.amaker.domain.event.Event
import com.backgu.amaker.domain.event.EventAssignedUser
import com.backgu.amaker.domain.notifiacation.chat.NewChat
import com.backgu.amaker.domain.user.User
import org.springframework.context.ApplicationEventPublisher
import org.springframework.stereotype.Service
Expand All @@ -42,6 +44,7 @@ class ChatFacadeService(
private val eventAssignedUserService: EventAssignedUserService,
private val chatUserCacheFacadeService: ChatUserCacheFacadeService,
private val eventPublisher: ApplicationEventPublisher,
private val notificationEventService: NotificationEventService,
) {
@Transactional
fun createChat(
Expand All @@ -57,6 +60,7 @@ class ChatFacadeService(
chatRoomService.save(chatRoom.updateLastChatId(chat))

eventPublisher.publishEvent(DefaultChatSaveEvent.of(chatRoomId, chat.createDefaultChatWithUser(user)))
notificationEventService.publishNotificationEvent(NewChat.of(user, chat, chatRoom))

return DefaultChatWithUserDto.of(chat, user)
}
Expand All @@ -66,8 +70,6 @@ class ChatFacadeService(
userId: String,
chatQuery: ChatQuery,
): ChatListDto {
markMostRecentChatAsRead(chatQuery.chatRoomId, userId)

val cachedChats =
chatUserCacheFacadeService.findPreviousChats(chatQuery.chatRoomId, chatQuery.cursor, chatQuery.size)
val dbQuerySize = chatQuery.size - cachedChats.size
Expand Down Expand Up @@ -113,9 +115,6 @@ class ChatFacadeService(
?.let { return ChatListDto.of(chatQuery, it.map { chatWithUser -> ChatWithUserDto.of(chatWithUser) }) }

val chatList = chatQueryService.findAfterChatList(chatQuery.chatRoomId, chatQuery.cursor, chatQuery.size)
for (defaultChatWithUser in chatList) {
println(defaultChatWithUser.id)
}

val eventMap =
eventService.findEventByIdsToMap(chatList.filter { ChatType.isEventChat(it.chatType) }.map { it.id })
Expand All @@ -142,19 +141,27 @@ class ChatFacadeService(
chatUserCacheFacadeService.findChat(chatRoomId, it)
}

if (cachedChat != null) return ChatWithUserDto.of(cachedChat)
if (cachedChat != null) {
markMostRecentChatAsRead(chatRoomId, userId)
return ChatWithUserDto.of(cachedChat)
}

val chat =
chatQueryService.getOneWithUser(
chatRoomUser.lastReadChatId ?: chatRoomService.getById(chatRoomId).lastChatId,
)

val chat = chatQueryService.getOneWithUser(chatRoomUser.lastReadChatId)
markMostRecentChatAsRead(chatRoomId, userId)

if (!ChatType.isEventChat(chat.chatType)) return DefaultChatWithUserDto.of(chat)
if (!ChatType.isEventChat(chat.chatType)) {
return DefaultChatWithUserDto.of(chat)
}

val event = eventService.getEventById(chat.id)
val eventAssignedUsers = eventAssignedUserService.findAllByEventId(event.id)
val userMap = userService.findAllByUserIdsToMap(eventAssignedUsers.map { it.userId })
val eventUsers = eventAssignedUsers.mapNotNull { userMap[it.userId] }

markMostRecentChatAsRead(chatRoomId, userId)

return EventChatWithUserDto.of(
chat,
EventWithUserDto.of(event, eventUsers, eventAssignedUsers.count { it.isFinished }),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.backgu.amaker.api.config

import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Configuration

@Configuration
@ConfigurationProperties(prefix = "spring.data.redis.cluster")
class ClusterConfigProperties {
lateinit var nodes: List<String>
var maxRedirects: Int = 3
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.backgu.amaker.api.config

import io.lettuce.core.SocketOptions
import io.lettuce.core.cluster.ClusterClientOptions
import io.lettuce.core.cluster.ClusterTopologyRefreshOptions
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Profile
import org.springframework.data.redis.connection.RedisClusterConfiguration
import org.springframework.data.redis.connection.RedisConnectionFactory
import org.springframework.data.redis.connection.RedisPassword
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory
import org.springframework.data.redis.core.RedisTemplate
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories
import org.springframework.data.redis.serializer.StringRedisSerializer
import java.time.Duration

@Configuration
@Profile("prod")
@EnableRedisRepositories
class ProdRedisConfig(
private val clusterConfigProperties: ClusterConfigProperties,
) {
@Value("\${spring.data.redis.password}")
lateinit var password: String

@Bean
fun redisConnectionFactory(): RedisConnectionFactory {
val clusterConfiguration = RedisClusterConfiguration(clusterConfigProperties.nodes)
clusterConfiguration.maxRedirects = clusterConfigProperties.maxRedirects
clusterConfiguration.password = RedisPassword.of(password)

val socketOptions =
SocketOptions
.builder()
.connectTimeout(Duration.ofMillis(100L))
.keepAlive(true)
.build()

val clusterTopologyRefreshOptions =
ClusterTopologyRefreshOptions
.builder()
.dynamicRefreshSources(true)
.enableAllAdaptiveRefreshTriggers()
.enablePeriodicRefresh(Duration.ofMinutes(30L))
.build()

val clientOptions =
ClusterClientOptions
.builder()
.topologyRefreshOptions(clusterTopologyRefreshOptions)
.socketOptions(socketOptions)
.build()

val clientConfiguration =
LettuceClientConfiguration
.builder()
.clientOptions(clientOptions)
.commandTimeout(Duration.ofMillis(3000L))
.build()

return LettuceConnectionFactory(clusterConfiguration, clientConfiguration)
}

@Bean
fun redisTemplate(): RedisTemplate<String, Any> {
val template = RedisTemplate<String, Any>()
template.connectionFactory = redisConnectionFactory()
template.keySerializer = StringRedisSerializer()
template.valueSerializer = StringRedisSerializer()
return template
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.backgu.amaker.api.config

import org.redisson.Redisson
import org.redisson.api.RedissonClient
import org.redisson.config.Config
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Profile

@Configuration
@Profile("prod")
class ProdRedissonConfig(
private val clusterConfigProperties: ClusterConfigProperties,
) {
@Value("\${spring.data.redis.password}")
lateinit var password: String

@Bean
fun redissonClient(): RedissonClient {
val config = Config()
val clusterServersConfig =
config
.useClusterServers()
.setScanInterval(2000)
.setConnectTimeout(100)
.setTimeout(3000)
.setRetryAttempts(3)
.setRetryInterval(1500)

clusterConfigProperties.nodes.forEach { node ->
clusterServersConfig.addNodeAddress("redis://$node")
}

if (password.isNotEmpty()) {
clusterServersConfig.setPassword(password)
}

return Redisson.create(config)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package com.backgu.amaker.api.config
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Profile
import org.springframework.data.redis.connection.RedisConnectionFactory
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory
import org.springframework.data.redis.core.RedisTemplate
import org.springframework.data.redis.serializer.StringRedisSerializer

@Profile("!prod")
@Configuration
@ConfigurationProperties(prefix = "spring.data.redis")
class RedisConfig {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import org.redisson.api.RedissonClient
import org.redisson.config.Config
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Profile

@Profile("!prod")
@Configuration
class RedissonConfig(
private val redisConfig: RedisConfig,
Expand Down
Loading

0 comments on commit 4e8c84e

Please sign in to comment.