fix(dm): WebSocket 연결 완료 시점을 보정한다
This commit is contained in:
@@ -42,10 +42,12 @@ class DmChatRoomViewModel(
|
|||||||
private var nextCursor: Long? = null
|
private var nextCursor: Long? = null
|
||||||
private var isLoadingOlder: Boolean = false
|
private var isLoadingOlder: Boolean = false
|
||||||
private var isSending: Boolean = false
|
private var isSending: Boolean = false
|
||||||
|
private var isRealtimeJoining: Boolean = false
|
||||||
private var isRealtimeConnected: Boolean = false
|
private var isRealtimeConnected: Boolean = false
|
||||||
private var shouldReconnectRealtime: Boolean = false
|
private var shouldReconnectRealtime: Boolean = false
|
||||||
private var currentAuthToken: String = ""
|
private var currentAuthToken: String = ""
|
||||||
private var currentRealtimeToken: String = ""
|
private var currentRealtimeToken: String = ""
|
||||||
|
private var currentRealtimeRoomId: Long = 0L
|
||||||
private var reconnectDisposable: Disposable? = null
|
private var reconnectDisposable: Disposable? = null
|
||||||
private var localMessageSequence: Long = 0L
|
private var localMessageSequence: Long = 0L
|
||||||
private val mainHandler = Handler(Looper.getMainLooper())
|
private val mainHandler = Handler(Looper.getMainLooper())
|
||||||
@@ -179,10 +181,14 @@ class DmChatRoomViewModel(
|
|||||||
|
|
||||||
private fun connectRealtime(token: String) {
|
private fun connectRealtime(token: String) {
|
||||||
val roomId = currentRoomId
|
val roomId = currentRoomId
|
||||||
if (roomId <= 0L || isRealtimeConnected || !shouldReconnectRealtime && currentRealtimeToken.isNotEmpty()) return
|
if (roomId <= 0L || isRealtimeConnected && currentRealtimeRoomId == roomId) return
|
||||||
|
if (isRealtimeJoining && currentRealtimeRoomId == roomId) return
|
||||||
|
if (!shouldReconnectRealtime && currentRealtimeToken.isNotEmpty() && currentRealtimeRoomId == roomId) return
|
||||||
|
|
||||||
currentRealtimeToken = token
|
currentRealtimeToken = token
|
||||||
isRealtimeConnected = true
|
currentRealtimeRoomId = roomId
|
||||||
|
isRealtimeJoining = true
|
||||||
|
isRealtimeConnected = false
|
||||||
shouldReconnectRealtime = true
|
shouldReconnectRealtime = true
|
||||||
reconnectDisposable?.dispose()
|
reconnectDisposable?.dispose()
|
||||||
reconnectDisposable = null
|
reconnectDisposable = null
|
||||||
@@ -195,6 +201,7 @@ class DmChatRoomViewModel(
|
|||||||
|
|
||||||
override fun onFailure(throwable: Throwable) {
|
override fun onFailure(throwable: Throwable) {
|
||||||
scheduleRealtimeCallback {
|
scheduleRealtimeCallback {
|
||||||
|
isRealtimeJoining = false
|
||||||
isRealtimeConnected = false
|
isRealtimeConnected = false
|
||||||
throwable.message?.let { Logger.e(it) }
|
throwable.message?.let { Logger.e(it) }
|
||||||
scheduleRealtimeReconnect()
|
scheduleRealtimeReconnect()
|
||||||
@@ -211,6 +218,8 @@ class DmChatRoomViewModel(
|
|||||||
|
|
||||||
shouldReconnectRealtime = false
|
shouldReconnectRealtime = false
|
||||||
currentRealtimeToken = ""
|
currentRealtimeToken = ""
|
||||||
|
currentRealtimeRoomId = 0L
|
||||||
|
isRealtimeJoining = false
|
||||||
isRealtimeConnected = false
|
isRealtimeConnected = false
|
||||||
reconnectDisposable?.dispose()
|
reconnectDisposable?.dispose()
|
||||||
reconnectDisposable = null
|
reconnectDisposable = null
|
||||||
@@ -247,6 +256,9 @@ class DmChatRoomViewModel(
|
|||||||
mainHandler.removeCallbacksAndMessages(null)
|
mainHandler.removeCallbacksAndMessages(null)
|
||||||
reconnectDisposable?.dispose()
|
reconnectDisposable?.dispose()
|
||||||
reconnectDisposable = null
|
reconnectDisposable = null
|
||||||
|
currentRealtimeRoomId = 0L
|
||||||
|
isRealtimeJoining = false
|
||||||
|
isRealtimeConnected = false
|
||||||
repository.closeSocket()
|
repository.closeSocket()
|
||||||
super.onCleared()
|
super.onCleared()
|
||||||
}
|
}
|
||||||
@@ -329,7 +341,11 @@ class DmChatRoomViewModel(
|
|||||||
|
|
||||||
private fun handleSocketEvent(event: DmChatSocketEvent, token: String) {
|
private fun handleSocketEvent(event: DmChatSocketEvent, token: String) {
|
||||||
when (event) {
|
when (event) {
|
||||||
DmChatSocketEvent.Joined -> syncLatestMessagesAfterReconnect(token = token)
|
DmChatSocketEvent.Joined -> {
|
||||||
|
isRealtimeJoining = false
|
||||||
|
isRealtimeConnected = true
|
||||||
|
syncLatestMessagesAfterReconnect(token = token)
|
||||||
|
}
|
||||||
is DmChatSocketEvent.Message -> onRealtimeMessage(event.message)
|
is DmChatSocketEvent.Message -> onRealtimeMessage(event.message)
|
||||||
is DmChatSocketEvent.SendAck -> handleSendAck(event.requestId, event.message)
|
is DmChatSocketEvent.SendAck -> handleSendAck(event.requestId, event.message)
|
||||||
is DmChatSocketEvent.Error -> event.requestId?.let { markLocalMessageFailed(it) }
|
is DmChatSocketEvent.Error -> event.requestId?.let { markLocalMessageFailed(it) }
|
||||||
|
|||||||
@@ -323,9 +323,11 @@ class DmChatRoomViewModelTest {
|
|||||||
viewModel.enter(roomId = 10L, creatorId = 0L)
|
viewModel.enter(roomId = 10L, creatorId = 0L)
|
||||||
|
|
||||||
viewModel.connectRealtime()
|
viewModel.connectRealtime()
|
||||||
|
assertEquals(false, viewModel.isRealtimeConnectedForTest())
|
||||||
socketFactory.emitJoined()
|
socketFactory.emitJoined()
|
||||||
|
|
||||||
assertEquals(listOf(RealtimeConnectCall("test-token", 10L)), socketFactory.connectCalls)
|
assertEquals(listOf(RealtimeConnectCall("test-token", 10L)), socketFactory.connectCalls)
|
||||||
|
assertEquals(true, viewModel.isRealtimeConnectedForTest())
|
||||||
assertEquals(listOf(MessagesCall("Bearer test-token", 10L, null, 20)), api.messagesCalls)
|
assertEquals(listOf(MessagesCall("Bearer test-token", 10L, null, 20)), api.messagesCalls)
|
||||||
val state = viewModel.chatRoomStateLiveData.requireValue() as DmChatRoomUiState.Content
|
val state = viewModel.chatRoomStateLiveData.requireValue() as DmChatRoomUiState.Content
|
||||||
assertEquals(listOf(1L, 2L), state.messages.map { it.messageId })
|
assertEquals(listOf(1L, 2L), state.messages.map { it.messageId })
|
||||||
@@ -340,6 +342,8 @@ class DmChatRoomViewModelTest {
|
|||||||
viewModel.connectRealtime()
|
viewModel.connectRealtime()
|
||||||
|
|
||||||
assertEquals(listOf(RealtimeConnectCall("test-token", 10L)), socketFactory.connectCalls)
|
assertEquals(listOf(RealtimeConnectCall("test-token", 10L)), socketFactory.connectCalls)
|
||||||
|
assertEquals(1, socketFactory.webSocket.sentTexts.size)
|
||||||
|
assertEquals("JOIN_ROOM", socketFactory.webSocket.sentJsonAt(0).get("type").asString)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -651,6 +655,12 @@ class DmChatRoomViewModelTest {
|
|||||||
method.isAccessible = true
|
method.isAccessible = true
|
||||||
method.invoke(this)
|
method.invoke(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun DmChatRoomViewModel.isRealtimeConnectedForTest(): Boolean {
|
||||||
|
val field = DmChatRoomViewModel::class.java.getDeclaredField("isRealtimeConnected")
|
||||||
|
field.isAccessible = true
|
||||||
|
return field.getBoolean(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user