Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update conversation info when out of sync #2306

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,15 @@ class DebugScope internal constructor(
get() = MessageSendFailureHandlerImpl(
userRepository,
clientRepository,
<<<<<<< HEAD
messageRepository,
messageSendingScheduler,
conversationRepository
=======
conversationRepository,
messageRepository,
messageSendingScheduler
>>>>>>> 3a80367c0d (feat: update conversation info when out of sync (#2287))
)

private val sessionEstablisher: SessionEstablisher
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,11 @@ import com.wire.kalium.logic.data.properties.UserPropertyRepository
import com.wire.kalium.logic.data.sync.IncrementalSyncRepository
import com.wire.kalium.logic.data.sync.SlowSyncRepository
import com.wire.kalium.logic.data.user.UserRepository
<<<<<<< HEAD
import com.wire.kalium.logic.feature.asset.GetAssetMessagesForConversationUseCase
import com.wire.kalium.logic.feature.asset.GetAssetMessagesForConversationUseCaseImpl
=======
>>>>>>> 3a80367c0d (feat: update conversation info when out of sync (#2287))
import com.wire.kalium.logic.feature.asset.GetMessageAssetUseCase
import com.wire.kalium.logic.feature.asset.GetMessageAssetUseCaseImpl
import com.wire.kalium.logic.feature.asset.ScheduleNewAssetMessageUseCase
Expand Down Expand Up @@ -102,9 +105,15 @@ class MessageScope internal constructor(
get() = MessageSendFailureHandlerImpl(
userRepository,
clientRepository,
<<<<<<< HEAD
messageRepository,
messageSendingScheduler,
conversationRepository
=======
conversationRepository,
messageRepository,
messageSendingScheduler
>>>>>>> 3a80367c0d (feat: update conversation info when out of sync (#2287))
)

private val sessionEstablisher: SessionEstablisher
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ import com.wire.kalium.logic.CoreFailure
import com.wire.kalium.logic.NetworkFailure
import com.wire.kalium.logic.StorageFailure
import com.wire.kalium.logic.data.client.ClientRepository
<<<<<<< HEAD
import com.wire.kalium.logic.data.conversation.ClientId
=======
>>>>>>> 3a80367c0d (feat: update conversation info when out of sync (#2287))
import com.wire.kalium.logic.data.conversation.ConversationRepository
import com.wire.kalium.logic.data.id.ConversationId
import com.wire.kalium.logic.data.message.MessageRepository
Expand Down Expand Up @@ -69,6 +72,7 @@ interface MessageSendFailureHandler {
class MessageSendFailureHandlerImpl internal constructor(
private val userRepository: UserRepository,
private val clientRepository: ClientRepository,
private val conversationRepository: ConversationRepository,
private val messageRepository: MessageRepository,
private val messageSendingScheduler: MessageSendingScheduler,
private val conversationRepository: ConversationRepository,
Expand All @@ -78,6 +82,7 @@ class MessageSendFailureHandlerImpl internal constructor(
sendFailure: ProteusSendMessageFailure,
conversationId: ConversationId?
): Either<CoreFailure, Unit> =
<<<<<<< HEAD
handleDeletedClients(sendFailure.deletedClientsOfUsers)
.map { usersWithNoClientsRemaining ->
sendFailure.missingClientsOfUsers.keys + usersWithNoClientsRemaining
Expand All @@ -87,6 +92,24 @@ class MessageSendFailureHandlerImpl internal constructor(
updateConversationInfo(sendFailure, conversationId)
}.flatMap {
addMissingClients(sendFailure.missingClientsOfUsers)
=======
// TODO(optimization): add/remove members to/from conversation
// TODO(optimization): remove clients from conversation
userRepository
.fetchUsersByIds(sendFailure.missingClientsOfUsers.keys)
.flatMap {
conversationId?.let {
conversationRepository.fetchConversation(conversationId)
} ?: Either.Right(Unit)
}
.flatMap {
sendFailure
.missingClientsOfUsers
.entries
.foldToEitherWhileRight(Unit) { entry, _ ->
clientRepository.storeUserClientIdList(entry.key, entry.value)
}
>>>>>>> 3a80367c0d (feat: update conversation info when out of sync (#2287))
}

private suspend fun updateConversationInfo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,11 @@ internal class MessageSenderImpl internal constructor(
"Proteus $action Failure: { \"message\" : \"${messageLogString}\", \"errorInfo\" : \"${failure}\" }"
)
messageSendFailureHandler
<<<<<<< HEAD
.handleClientsHaveChangedFailure(failure, conversationId)
=======
.handleClientsHaveChangedFailure(failure, conversationId = conversationId)
>>>>>>> 3a80367c0d (feat: update conversation info when out of sync (#2287))
.flatMap {
logger.w("Retrying After Proteus $action Failure: { \"message\" : \"${messageLogString}\"}")
retry()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ import com.wire.kalium.logic.NetworkFailure
import com.wire.kalium.logic.StorageFailure
import com.wire.kalium.logic.data.conversation.ClientId
import com.wire.kalium.logic.data.conversation.ConversationRepository
<<<<<<< HEAD
=======
import com.wire.kalium.logic.data.id.ConversationId
>>>>>>> 3a80367c0d (feat: update conversation info when out of sync (#2287))
import com.wire.kalium.logic.data.message.MessageRepository
import com.wire.kalium.logic.data.user.UserId
import com.wire.kalium.logic.data.user.UserRepository
Expand Down Expand Up @@ -64,6 +68,14 @@ class MessageSendFailureHandlerTest {
val failureData = ProteusSendMessageFailure(mapOf(arrangement.userOne, arrangement.userTwo), mapOf(), mapOf(), null)

messageSendFailureHandler.handleClientsHaveChangedFailure(failureData, null)
<<<<<<< HEAD
=======

verify(arrangement.userRepository)
.suspendFunction(arrangement.userRepository::fetchUsersByIds)
.with(eq(failureData.missingClientsOfUsers.keys))
.wasInvoked(once)
>>>>>>> 3a80367c0d (feat: update conversation info when out of sync (#2287))
}

@Test
Expand Down Expand Up @@ -94,9 +106,13 @@ class MessageSendFailureHandlerTest {
.arrange()
val failureData = ProteusSendMessageFailure(mapOf(arrangement.userOne, arrangement.userTwo), mapOf(), mapOf(), null)

<<<<<<< HEAD
val result = messageSendFailureHandler.handleClientsHaveChangedFailure(
failureData, null
)
=======
val result = messageSendFailureHandler.handleClientsHaveChangedFailure(failureData, null)
>>>>>>> 3a80367c0d (feat: update conversation info when out of sync (#2287))
result.shouldFail()
assertEquals(Either.Left(failure), result)
}
Expand Down Expand Up @@ -174,6 +190,7 @@ class MessageSendFailureHandlerTest {
}

@Test
<<<<<<< HEAD
fun givenDeletedClientsError_whenAllUserClientsAreDeleted_thenClientsShouldBeRemovedAndUserIndoShouldBeFetched() = runTest {
// 1. remove clients
// 2. return the list of users that have no clients left
Expand Down Expand Up @@ -334,6 +351,55 @@ class MessageSendFailureHandlerTest {
}

class Arrangement : ClientRepositoryArrangement by ClientRepositoryArrangementImpl() {
=======
fun givenMissingClientsError_whenAConversationIdIsProvided_thenUpdateConversationInfo() = runTest {
val (arrangement, messageSendFailureHandler) = Arrangement()
.withFetchUsersByIdSuccess()
.withStoreUserClientIdListSuccess()
.withFetchConversation(Either.Right(Unit))
.arrange()
val failureData = ProteusSendMessageFailure(mapOf(arrangement.userOne, arrangement.userTwo), mapOf(), mapOf(), null)

messageSendFailureHandler.handleClientsHaveChangedFailure(failureData, arrangement.conversationId)

verify(arrangement.userRepository)
.suspendFunction(arrangement.userRepository::fetchUsersByIds)
.with(eq(failureData.missingClientsOfUsers.keys))
.wasInvoked(once)

verify(arrangement.conversationRepository)
.suspendFunction(arrangement.conversationRepository::fetchConversation)
.with(any())
.wasInvoked(exactly = once)
}

@Test
fun givenMissingClientsError_whenNoConversationIdIsProvided_thenUpdateConversationInfo() = runTest {
val (arrangement, messageSendFailureHandler) = Arrangement()
.withFetchUsersByIdSuccess()
.withStoreUserClientIdListSuccess()
.arrange()
val failureData = ProteusSendMessageFailure(mapOf(arrangement.userOne, arrangement.userTwo), mapOf(), mapOf(), null)

messageSendFailureHandler.handleClientsHaveChangedFailure(failureData, null)

verify(arrangement.userRepository)
.suspendFunction(arrangement.userRepository::fetchUsersByIds)
.with(eq(failureData.missingClientsOfUsers.keys))
.wasInvoked(once)

verify(arrangement.conversationRepository)
.suspendFunction(arrangement.conversationRepository::fetchConversation)
.with(any())
.wasNotInvoked()
}

class Arrangement {

@Mock
internal val clientRepository = mock(classOf<ClientRepository>())

>>>>>>> 3a80367c0d (feat: update conversation info when out of sync (#2287))
@Mock
internal val userRepository = mock(classOf<UserRepository>())

Expand All @@ -344,15 +410,25 @@ class MessageSendFailureHandlerTest {
val messageSendingScheduler = configure(mock(MessageSendingScheduler::class)) { stubsUnitByDefault = true }

@Mock
<<<<<<< HEAD
val conversationRepository = mock(classOf<ConversationRepository>())
=======
val conversationRepository = configure(mock(ConversationRepository::class)) { stubsUnitByDefault = true }
>>>>>>> 3a80367c0d (feat: update conversation info when out of sync (#2287))

private val messageSendFailureHandler: MessageSendFailureHandler =
MessageSendFailureHandlerImpl(
userRepository,
clientRepository,
<<<<<<< HEAD
messageRepository,
messageSendingScheduler,
conversationRepository
=======
conversationRepository,
messageRepository,
messageSendingScheduler
>>>>>>> 3a80367c0d (feat: update conversation info when out of sync (#2287))
)
val userOne: Pair<UserId, List<ClientId>> =
UserId("userId1", "anta.wire") to listOf(ClientId("clientId"), ClientId("secondClientId"))
Expand All @@ -377,6 +453,23 @@ class MessageSendFailureHandlerTest {
.thenReturn(Either.Left(failure))
}

<<<<<<< HEAD
=======
fun withStoreUserClientIdListSuccess() = apply {
given(clientRepository)
.suspendFunction(clientRepository::storeUserClientIdList)
.whenInvokedWith(any(), any())
.thenReturn(Either.Right(Unit))
}

fun withStoreUserClientIdListFailure(failure: StorageFailure) = apply {
given(clientRepository)
.suspendFunction(clientRepository::storeUserClientIdList)
.whenInvokedWith(any(), any())
.thenReturn(Either.Left(failure))
}

>>>>>>> 3a80367c0d (feat: update conversation info when out of sync (#2287))
fun withUpdateMessageStatusSuccess() = apply {
given(messageRepository)
.suspendFunction(messageRepository::updateMessageStatus)
Expand Down