Skip to content

Commit

Permalink
fix: duplicated conversation timer change event [WPB-286] (#1815)
Browse files Browse the repository at this point in the history
* fix: duplicated conversation timer change event

* detekt fix
  • Loading branch information
Garzas authored Jun 21, 2023
1 parent 26bd923 commit 4c639f1
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,22 @@ internal class ConversationMessageTimerEventHandlerImpl(

override suspend fun handle(event: Event.Conversation.ConversationMessageTimer) {
updateMessageTimer(event)
.onSuccess {
val message = Message.System(
uuid4().toString(),
MessageContent.ConversationMessageTimerChanged(
messageTimer = event.messageTimer
),
event.conversationId,
DateTimeUtil.currentIsoDateTimeString(),
event.senderUserId,
Message.Status.SENT,
Message.Visibility.VISIBLE
)
.onSuccess { updated ->
if (updated) {
val message = Message.System(
uuid4().toString(),
MessageContent.ConversationMessageTimerChanged(
messageTimer = event.messageTimer
),
event.conversationId,
DateTimeUtil.currentIsoDateTimeString(),
event.senderUserId,
Message.Status.SENT,
Message.Visibility.VISIBLE
)

persistMessage(message)
persistMessage(message)
}
kaliumLogger
.logEventProcessing(
EventLoggingStatus.SUCCESS,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ object TestEvent {
transient = false
)

fun timerChanged(eventId: String = "eventId") = Event.Conversation.ConversationMessageTimer(
id = eventId,
conversationId = TestConversation.ID,
transient = false,
messageTimer = 3000,
senderUserId = TestUser.USER_ID
)

fun userPropertyReadReceiptMode(eventId: String = "eventId") = Event.UserProperty.ReadReceiptModeSet(
id = eventId,
transient = false,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/

package com.wire.kalium.logic.sync.receiver.conversation

import com.wire.kalium.logic.CoreFailure
import com.wire.kalium.logic.data.message.PersistMessageUseCase
import com.wire.kalium.logic.framework.TestEvent
import com.wire.kalium.logic.functional.Either
import com.wire.kalium.persistence.dao.ConversationDAO
import io.mockative.Mock
import io.mockative.any
import io.mockative.classOf
import io.mockative.given
import io.mockative.mock
import io.mockative.once
import io.mockative.verify
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import kotlin.test.Test

@OptIn(ExperimentalCoroutinesApi::class)
class ConversationMessageTimerEventHandlerTest {

@Test
fun givenAConversationMessageTimerEvent_whenItGetsUpdated_thenShouldPersistSystemMessage() = runTest {
val event = TestEvent.timerChanged()
val (arrangement, eventHandler) = Arrangement()
.withConversationUpdateMessageTimer(true)
.withPersistMessage(Either.Right(Unit))
.arrange()

eventHandler.handle(event)

with(arrangement) {
verify(persistMessageUseCase)
.suspendFunction(persistMessageUseCase::invoke)
.with(any())
.wasInvoked(once)
}
}

@Test
fun givenAConversationMessageTimerEvent_whenIsNotUpdated_thenShouldNotPersistSystemMessage() = runTest {
val event = TestEvent.timerChanged()
val (arrangement, eventHandler) = Arrangement()
.withConversationUpdateMessageTimer(false)
.withPersistMessage(Either.Right(Unit))
.arrange()

eventHandler.handle(event)

with(arrangement) {
verify(persistMessageUseCase)
.suspendFunction(persistMessageUseCase::invoke)
.with(any())
.wasNotInvoked()
}
}

private class Arrangement {

@Mock
val conversationDAO = mock(classOf<ConversationDAO>())

@Mock
val persistMessageUseCase = mock(classOf<PersistMessageUseCase>())

private val conversationMessageTimerEventHandler: ConversationMessageTimerEventHandler = ConversationMessageTimerEventHandlerImpl(
conversationDAO,
persistMessageUseCase
)

fun withConversationUpdateMessageTimer(updated: Boolean) = apply {
given(conversationDAO)
.suspendFunction(conversationDAO::updateMessageTimer)
.whenInvokedWith(any())
.thenReturn(updated)
}

fun withPersistMessage(result: Either<CoreFailure, Unit>) = apply {
given(persistMessageUseCase)
.suspendFunction(persistMessageUseCase::invoke)
.whenInvokedWith(any())
.thenReturn(result)
}

fun arrange() = this to conversationMessageTimerEventHandler
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,9 @@ UPDATE Conversation
SET message_timer = ?
WHERE qualified_id = ?;

getMessageTimer:
SELECT message_timer FROM Conversation WHERE qualified_id = ?;

updateUserMessageTimer:
UPDATE Conversation
SET user_message_timer = ?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,6 @@ interface ConversationDAO {
suspend fun updateConversationReceiptMode(conversationID: QualifiedIDEntity, receiptMode: ConversationEntity.ReceiptMode)
suspend fun updateGuestRoomLink(conversationId: QualifiedIDEntity, link: String?)
suspend fun observeGuestRoomLinkByConversationId(conversationId: QualifiedIDEntity): Flow<String?>
suspend fun updateMessageTimer(conversationId: QualifiedIDEntity, messageTimer: Long?)
suspend fun updateMessageTimer(conversationId: QualifiedIDEntity, messageTimer: Long?): Boolean
suspend fun updateUserMessageTimer(conversationId: QualifiedIDEntity, messageTimer: Long?)
}
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,12 @@ class ConversationDAOImpl(
}.flowOn(coroutineContext)

override suspend fun updateMessageTimer(conversationId: QualifiedIDEntity, messageTimer: Long?) = withContext(coroutineContext) {
conversationQueries.updateMessageTimer(messageTimer, conversationId)
val previousTimer = conversationQueries.getMessageTimer(conversationId).executeAsOneOrNull()?.message_timer
val updated = previousTimer != messageTimer
if (updated) {
conversationQueries.updateMessageTimer(messageTimer, conversationId)
}
updated
}

override suspend fun updateUserMessageTimer(conversationId: QualifiedIDEntity, messageTimer: Long?) = withContext(coroutineContext) {
Expand Down

0 comments on commit 4c639f1

Please sign in to comment.