Skip to content

Commit

Permalink
feature: configure redis with chat service
Browse files Browse the repository at this point in the history
  • Loading branch information
hyun98 committed Oct 15, 2023
1 parent 31401b5 commit adada6a
Show file tree
Hide file tree
Showing 74 changed files with 316 additions and 169 deletions.
19 changes: 14 additions & 5 deletions front-test-bed/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ const stompClient = new StompJs.Client({
brokerURL: 'ws://localhost:8080/ws-stomp'
});

// var channelId = ""

stompClient.onConnect = (frame) => {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/sub/greetings', (greeting) => {
showGreeting(JSON.parse(greeting.body).content);
stompClient.subscribe('/sub/chat/channel/' + $("#channelId").val(), (message) => {
console.log(JSON.parse(message.body))
showMessage(JSON.parse(message.body).content);
});
};

Expand Down Expand Up @@ -43,12 +46,18 @@ function disconnect() {

function sendName() {
stompClient.publish({
destination: "/pub/hello",
body: JSON.stringify({'name': $("#name").val()})
destination: "/pub/chat/message",
body: JSON.stringify(
{
"channelId": $("#channelId").val(),
"sender" : $("#name").val(),
"content" : $("#content").val()
}
)
});
}

function showGreeting(message) {
function showMessage(message) {
$("#greetings").append("<tr><td>" + message + "</td></tr>");
}

Expand Down
16 changes: 16 additions & 0 deletions front-test-bed/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,25 @@
<label for="name">What is your name?</label>
<input type="text" id="name" class="form-control" placeholder="Your name here...">
</div>
</form>
</div>
<div class="col-md-6">
<form class="form-inline">
<div class="form-group">
<label for="name">Content</label>
<input type="text" id="content" class="form-control" placeholder="Type your message...">
</div>
<button id="send" class="btn btn-default" type="submit">Send</button>
</form>
</div>
<div class="col-md-6">
<form class="form-inline">
<div class="form-group">
<label for="name">Set Channel Id</label>
<input type="text" id="channelId" class="form-control" placeholder="Set temp ChannelId">
</div>
</form>
</div>
</div>
<div class="row">
<div class="col-md-12">
Expand Down
5 changes: 5 additions & 0 deletions sns_service/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ repositories {

dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-websocket")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
Expand All @@ -34,11 +35,15 @@ dependencies {
implementation("io.micrometer:micrometer-registry-prometheus")
implementation ("net.logstash.logback:logstash-logback-encoder:7.3")
implementation ("io.github.microutils:kotlin-logging:3.0.5")

//embedded-redis
implementation("it.ozimov:embedded-redis:0.7.2")

compileOnly("org.projectlombok:lombok")
annotationProcessor("org.projectlombok:lombok")
testImplementation("org.springframework.boot:spring-boot-starter-test")
runtimeOnly("com.mysql:mysql-connector-j")
runtimeOnly("com.h2database:h2")
}

tasks.withType<KotlinCompile> {
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package joryu.sns_service.channel.entity

import jakarta.persistence.*
import joryu.sns_service.channel.enums.ChannelType
import java.io.Serializable
import java.util.*


@Table(name = "channel")
@Entity
class Channel(
channelName: String = "",

@Column(name = "channel_type")
val channelType: ChannelType = ChannelType.PERSONAL
) : Serializable {
@Id
val id: String = UUID.randomUUID().toString()

@OneToMany(mappedBy = "channel")
val channelUsers: MutableList<ChannelProfile> = mutableListOf()

@Column(name = "channel_name")
var channelName: String = channelName
private set

fun changeChannelName(newName: String) {
channelName = newName
}

fun addUserToChannel(user: ChannelProfile) {
channelUsers.add(user)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package joryu.sns_service.channel.entity

import jakarta.persistence.*
import joryu.sns_service.profile.entity.Profile
import java.io.Serializable

@Table(name = "channel_profile")
@Entity
class ChannelProfile(
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "channel_id")
var channel: Channel? = null,

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "profile_id")
var profile: Profile? = null
): Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long = 0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package joryu.sns_service.channel.enums

enum class ChannelType {
PERSONAL, GROUP
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package joryu.sns_service.channel.repository

import joryu.sns_service.channel.entity.ChannelProfile
import org.springframework.data.jpa.repository.JpaRepository

interface ChannelProfileRepository: JpaRepository<ChannelProfile, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package joryu.sns_service.channel.repository

import joryu.sns_service.channel.entity.Channel
import org.springframework.data.jpa.repository.JpaRepository

interface ChannelRepository: JpaRepository<Channel, String> {
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package joryu.sns_service.chat.config

import jakarta.annotation.PostConstruct
import jakarta.annotation.PreDestroy
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Profile
import redis.embedded.RedisServer


@Profile("local") // profile이 local일때만 활성화
@Configuration
class EmbeddedRedisConfig {

@Value("\${spring.data.redis.port}")
private val redisPort = 6379

private var redisServer: RedisServer? = null

@PostConstruct
fun redisServer() {
redisServer = RedisServer(redisPort)
redisServer?.start()
}

@PreDestroy
fun stopRedis() {
redisServer?.stop()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package joryu.sns_service.chat.config

import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary
import org.springframework.data.redis.connection.MessageListener
import org.springframework.data.redis.connection.RedisConnectionFactory
import org.springframework.data.redis.connection.RedisStandaloneConfiguration
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory
import org.springframework.data.redis.core.RedisTemplate
import org.springframework.data.redis.listener.ChannelTopic
import org.springframework.data.redis.listener.RedisMessageListenerContainer
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer
import org.springframework.data.redis.serializer.StringRedisSerializer


/**
* 채팅에 사용되는 redis 설정 관리
*/
@Configuration
@EnableRedisRepositories
class RedisConfig(
@Value("\${spring.data.redis.port:6379}")
private val port: Int,

@Value("\${spring.data.redis.host:localhost}")
private val host: String
) {

/**
* ChannelTopic 에 발행된 메시지를 처리하는 Listner 들을 설정한다.
*/
@Bean
@Primary
fun redisMessageListenerContainer(
redisConnectionFactory: RedisConnectionFactory,
chatMessageListenerAdapter: MessageListenerAdapter,
@Qualifier("chatChannelTopic") chatChannelTopic: ChannelTopic
): RedisMessageListenerContainer {
val container = RedisMessageListenerContainer()
container.setConnectionFactory(redisConnectionFactory)
container.addMessageListener(chatMessageListenerAdapter, chatChannelTopic)
return container
}

@Bean
fun redisConnectionFactory(): RedisConnectionFactory {
val redisStandaloneConfiguration = RedisStandaloneConfiguration()
redisStandaloneConfiguration.hostName = host
redisStandaloneConfiguration.port = port
return LettuceConnectionFactory(redisStandaloneConfiguration)
}

/**
* RedisMessageListenerContainer 로부터 메시지를 전달받는다.
* 메시지 처리 비즈니스 로직을 담은 Subscriber Bean 을 추가해준다.
*/
@Bean
fun chatMessageListenerAdapter(listener: MessageListener): MessageListenerAdapter {
return MessageListenerAdapter(listener, "onMessage")
}

/**
* 채팅 채널 토픽을 반환한다.
*/
@Bean(value = ["chatChannelTopic"])
fun chatChannelTopic(): ChannelTopic {
return ChannelTopic("chat")
}

/**
* Redis 데이터에 접근하는 redisTemplate 를 반환한다.
*/
@Bean
fun redisTemplate(connectionFactory: RedisConnectionFactory): RedisTemplate<String, Any> {
val redisTemplate = RedisTemplate<String, Any>()
redisTemplate.connectionFactory = connectionFactory
redisTemplate.keySerializer = StringRedisSerializer()
redisTemplate.valueSerializer = Jackson2JsonRedisSerializer(String::class.java)
return redisTemplate
}
}
Empty file.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package joryu.sns_service.chat.controller

import joryu.sns_service.chat.dto.ChatMessage
import joryu.sns_service.chat.service.ChatPublisher
import org.springframework.messaging.handler.annotation.MessageMapping
import org.springframework.stereotype.Controller

@Controller
class ChatMessageController(
private val chatPublisher: ChatPublisher
) {

/**
* /pub/chat/message 로 들어오는 메시징을 처리한다.
*/
@MessageMapping("/chat/message")
fun sendMessage(message: ChatMessage) {

chatPublisher.publish(message)
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package joryu.sns_service.chat.dto

data class ChatMessage(
val channelId: String,
val sender: String,
val content: String = "",
)
Loading

0 comments on commit adada6a

Please sign in to comment.