android, desktop: better handling of parallel updates of chats (#3204)
* android, desktop: better handling of parallel updates of chats * one more case
This commit is contained in:
parent
b956988a83
commit
8ffe1c23c1
@ -9,12 +9,14 @@ import chat.simplex.common.helpers.APPLICATION_ID
|
||||
import chat.simplex.common.helpers.requiresIgnoringBattery
|
||||
import chat.simplex.common.model.*
|
||||
import chat.simplex.common.model.ChatController.appPrefs
|
||||
import chat.simplex.common.model.ChatModel.updatingChatsMutex
|
||||
import chat.simplex.common.views.helpers.*
|
||||
import chat.simplex.common.views.onboarding.OnboardingStage
|
||||
import chat.simplex.common.platform.*
|
||||
import chat.simplex.common.views.call.RcvCallInvitation
|
||||
import com.jakewharton.processphoenix.ProcessPhoenix
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
@ -52,6 +54,7 @@ class SimplexApp: Application(), LifecycleEventObserver {
|
||||
Lifecycle.Event.ON_START -> {
|
||||
isAppOnForeground = true
|
||||
if (chatModel.chatRunning.value == true) {
|
||||
updatingChatsMutex.withLock {
|
||||
kotlin.runCatching {
|
||||
val currentUserId = chatModel.currentUser.value?.userId
|
||||
val chats = ArrayList(chatController.apiGetChats())
|
||||
@ -69,6 +72,7 @@ class SimplexApp: Application(), LifecycleEventObserver {
|
||||
}.onFailure { Log.e(TAG, it.stackTraceToString()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
Lifecycle.Event.ON_RESUME -> {
|
||||
isAppOnForeground = true
|
||||
if (chatModel.controller.appPrefs.onboardingStage.get() == OnboardingStage.OnboardingComplete) {
|
||||
|
@ -6,7 +6,6 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.font.*
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import chat.simplex.common.model.*
|
||||
import chat.simplex.common.platform.*
|
||||
import chat.simplex.common.ui.theme.*
|
||||
import chat.simplex.common.views.call.*
|
||||
@ -16,6 +15,8 @@ import chat.simplex.res.MR
|
||||
import dev.icerock.moko.resources.ImageResource
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.datetime.*
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.serialization.*
|
||||
@ -102,6 +103,8 @@ object ChatModel {
|
||||
val filesToDelete = mutableSetOf<File>()
|
||||
val simplexLinkMode by lazy { mutableStateOf(ChatController.appPrefs.simplexLinkMode.get()) }
|
||||
|
||||
var updatingChatsMutex: Mutex = Mutex()
|
||||
|
||||
fun getUser(userId: Long): User? = if (currentUser.value?.userId == userId) {
|
||||
currentUser.value
|
||||
} else {
|
||||
@ -198,7 +201,7 @@ object ChatModel {
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun addChatItem(cInfo: ChatInfo, cItem: ChatItem) {
|
||||
suspend fun addChatItem(cInfo: ChatInfo, cItem: ChatItem) = updatingChatsMutex.withLock {
|
||||
// update previews
|
||||
val i = getChatIndex(cInfo.id)
|
||||
val chat: Chat
|
||||
@ -221,10 +224,11 @@ object ChatModel {
|
||||
} else {
|
||||
addChat(Chat(chatInfo = cInfo, chatItems = arrayListOf(cItem)))
|
||||
}
|
||||
// add to current chat
|
||||
if (chatId.value == cInfo.id) {
|
||||
Log.d(TAG, "TODOCHAT: addChatItem: adding to chat ${chatId.value} from ${cInfo.id} ${cItem.id}, size ${chatItems.size}")
|
||||
withContext(Dispatchers.Main) {
|
||||
// add to current chat
|
||||
if (chatId.value == cInfo.id) {
|
||||
Log.d(TAG, "TODOCHAT: addChatItem: chatIds are equal, size ${chatItems.size}")
|
||||
// Prevent situation when chat item already in the list received from backend
|
||||
if (chatItems.none { it.id == cItem.id }) {
|
||||
if (chatItems.lastOrNull()?.id == ChatItem.TEMP_LIVE_CHAT_ITEM_ID) {
|
||||
@ -238,7 +242,7 @@ object ChatModel {
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun upsertChatItem(cInfo: ChatInfo, cItem: ChatItem): Boolean {
|
||||
suspend fun upsertChatItem(cInfo: ChatInfo, cItem: ChatItem): Boolean = updatingChatsMutex.withLock {
|
||||
// update previews
|
||||
val i = getChatIndex(cInfo.id)
|
||||
val chat: Chat
|
||||
@ -258,10 +262,10 @@ object ChatModel {
|
||||
addChat(Chat(chatInfo = cInfo, chatItems = arrayListOf(cItem)))
|
||||
res = true
|
||||
}
|
||||
// update current chat
|
||||
return if (chatId.value == cInfo.id) {
|
||||
Log.d(TAG, "TODOCHAT: upsertChatItem: upserting to chat ${chatId.value} from ${cInfo.id} ${cItem.id}, size ${chatItems.size}")
|
||||
withContext(Dispatchers.Main) {
|
||||
return withContext(Dispatchers.Main) {
|
||||
// update current chat
|
||||
if (chatId.value == cInfo.id) {
|
||||
val itemIndex = chatItems.indexOfFirst { it.id == cItem.id }
|
||||
if (itemIndex >= 0) {
|
||||
chatItems[itemIndex] = cItem
|
||||
@ -272,15 +276,15 @@ object ChatModel {
|
||||
Log.d(TAG, "TODOCHAT: upsertChatItem: added to chat $chatId from ${cInfo.id} ${cItem.id}, size ${chatItems.size}")
|
||||
true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun updateChatItem(cInfo: ChatInfo, cItem: ChatItem) {
|
||||
if (chatId.value == cInfo.id) {
|
||||
withContext(Dispatchers.Main) {
|
||||
if (chatId.value == cInfo.id) {
|
||||
val itemIndex = chatItems.indexOfFirst { it.id == cItem.id }
|
||||
if (itemIndex >= 0) {
|
||||
chatItems[itemIndex] = cItem
|
||||
|
@ -4,6 +4,7 @@ import chat.simplex.common.views.helpers.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import chat.simplex.common.model.ChatModel.updatingChatsMutex
|
||||
import dev.icerock.moko.resources.compose.painterResource
|
||||
import chat.simplex.common.platform.*
|
||||
import chat.simplex.common.ui.theme.*
|
||||
@ -16,6 +17,7 @@ import com.charleskorn.kaml.YamlConfiguration
|
||||
import chat.simplex.res.MR
|
||||
import com.russhwolf.settings.Settings
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.datetime.Instant
|
||||
import kotlinx.serialization.*
|
||||
@ -349,8 +351,10 @@ object ChatController {
|
||||
startReceiver()
|
||||
Log.d(TAG, "startChat: started")
|
||||
} else {
|
||||
updatingChatsMutex.withLock {
|
||||
val chats = apiGetChats()
|
||||
chatModel.updateChats(chats)
|
||||
}
|
||||
Log.d(TAG, "startChat: running")
|
||||
}
|
||||
} catch (e: Error) {
|
||||
@ -384,9 +388,11 @@ object ChatController {
|
||||
suspend fun getUserChatData() {
|
||||
chatModel.userAddress.value = apiGetUserAddress()
|
||||
chatModel.chatItemTTL.value = getChatItemTTL()
|
||||
updatingChatsMutex.withLock {
|
||||
val chats = apiGetChats()
|
||||
chatModel.updateChats(chats)
|
||||
}
|
||||
}
|
||||
|
||||
private fun startReceiver() {
|
||||
Log.d(TAG, "ChatController startReceiver")
|
||||
|
@ -20,11 +20,13 @@ import androidx.compose.ui.text.*
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import chat.simplex.common.model.*
|
||||
import chat.simplex.common.model.ChatModel.updatingChatsMutex
|
||||
import chat.simplex.common.ui.theme.*
|
||||
import chat.simplex.common.views.helpers.*
|
||||
import chat.simplex.common.views.usersettings.*
|
||||
import chat.simplex.common.platform.*
|
||||
import chat.simplex.res.MR
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.datetime.*
|
||||
import java.io.*
|
||||
import java.net.URI
|
||||
@ -620,8 +622,10 @@ private fun afterSetCiTTL(
|
||||
appFilesCountAndSize.value = directoryFileCountAndSize(appFilesDir.absolutePath)
|
||||
withApi {
|
||||
try {
|
||||
updatingChatsMutex.withLock {
|
||||
val chats = m.controller.apiGetChats()
|
||||
m.updateChats(chats)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "apiGetChats error: ${e.message}")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user