android, desktop: debug subscribed SMP queues (#4262)

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
This commit is contained in:
Stanislav Dmitrenko
2024-06-01 00:54:12 +07:00
committed by GitHub
parent b165603136
commit c251f5e2bd
4 changed files with 114 additions and 0 deletions
@@ -931,6 +931,20 @@ object ChatController {
return null
}
suspend fun apiContactQueueInfo(rh: Long?, contactId: Long): Pair<RcvMsgInfo?, QueueInfo>? {
val r = sendCmd(rh, CC.APIContactQueueInfo(contactId))
if (r is CR.QueueInfoR) return Pair(r.rcvMsgInfo, r.queueInfo)
apiErrorAlert("apiContactQueueInfo", generalGetString(MR.strings.error), r)
return null
}
suspend fun apiGroupMemberQueueInfo(rh: Long?, groupId: Long, groupMemberId: Long): Pair<RcvMsgInfo?, QueueInfo>? {
val r = sendCmd(rh, CC.APIGroupMemberQueueInfo(groupId, groupMemberId))
if (r is CR.QueueInfoR) return Pair(r.rcvMsgInfo, r.queueInfo)
apiErrorAlert("apiGroupMemberQueueInfo", generalGetString(MR.strings.error), r)
return null
}
suspend fun apiSwitchContact(rh: Long?, contactId: Long): ConnectionStats? {
val r = sendCmd(rh, CC.APISwitchContact(contactId))
if (r is CR.ContactSwitchStarted) return r.connectionStats
@@ -2507,6 +2521,8 @@ sealed class CC {
class ApiSetMemberSettings(val groupId: Long, val groupMemberId: Long, val memberSettings: GroupMemberSettings): CC()
class APIContactInfo(val contactId: Long): CC()
class APIGroupMemberInfo(val groupId: Long, val groupMemberId: Long): CC()
class APIContactQueueInfo(val contactId: Long): CC()
class APIGroupMemberQueueInfo(val groupId: Long, val groupMemberId: Long): CC()
class APISwitchContact(val contactId: Long): CC()
class APISwitchGroupMember(val groupId: Long, val groupMemberId: Long): CC()
class APIAbortSwitchContact(val contactId: Long): CC()
@@ -2652,6 +2668,8 @@ sealed class CC {
is ApiSetMemberSettings -> "/_member settings #$groupId $groupMemberId ${json.encodeToString(memberSettings)}"
is APIContactInfo -> "/_info @$contactId"
is APIGroupMemberInfo -> "/_info #$groupId $groupMemberId"
is APIContactQueueInfo -> "/_queue info @$contactId"
is APIGroupMemberQueueInfo -> "/_queue info #$groupId $groupMemberId"
is APISwitchContact -> "/_switch @$contactId"
is APISwitchGroupMember -> "/_switch #$groupId $groupMemberId"
is APIAbortSwitchContact -> "/_abort switch @$contactId"
@@ -2790,6 +2808,8 @@ sealed class CC {
is ApiSetMemberSettings -> "apiSetMemberSettings"
is APIContactInfo -> "apiContactInfo"
is APIGroupMemberInfo -> "apiGroupMemberInfo"
is APIContactQueueInfo -> "apiContactQueueInfo"
is APIGroupMemberQueueInfo -> "apiGroupMemberQueueInfo"
is APISwitchContact -> "apiSwitchContact"
is APISwitchGroupMember -> "apiSwitchGroupMember"
is APIAbortSwitchContact -> "apiAbortSwitchContact"
@@ -4197,6 +4217,7 @@ sealed class CR {
@Serializable @SerialName("networkConfig") class NetworkConfig(val networkConfig: NetCfg): CR()
@Serializable @SerialName("contactInfo") class ContactInfo(val user: UserRef, val contact: Contact, val connectionStats_: ConnectionStats? = null, val customUserProfile: Profile? = null): CR()
@Serializable @SerialName("groupMemberInfo") class GroupMemberInfo(val user: UserRef, val groupInfo: GroupInfo, val member: GroupMember, val connectionStats_: ConnectionStats? = null): CR()
@Serializable @SerialName("queueInfo") class QueueInfoR(val user: UserRef, val rcvMsgInfo: RcvMsgInfo?, val queueInfo: QueueInfo): CR()
@Serializable @SerialName("contactSwitchStarted") class ContactSwitchStarted(val user: UserRef, val contact: Contact, val connectionStats: ConnectionStats): CR()
@Serializable @SerialName("groupMemberSwitchStarted") class GroupMemberSwitchStarted(val user: UserRef, val groupInfo: GroupInfo, val member: GroupMember, val connectionStats: ConnectionStats): CR()
@Serializable @SerialName("contactSwitchAborted") class ContactSwitchAborted(val user: UserRef, val contact: Contact, val connectionStats: ConnectionStats): CR()
@@ -4368,6 +4389,7 @@ sealed class CR {
is NetworkConfig -> "networkConfig"
is ContactInfo -> "contactInfo"
is GroupMemberInfo -> "groupMemberInfo"
is QueueInfoR -> "queueInfo"
is ContactSwitchStarted -> "contactSwitchStarted"
is GroupMemberSwitchStarted -> "groupMemberSwitchStarted"
is ContactSwitchAborted -> "contactSwitchAborted"
@@ -4529,6 +4551,7 @@ sealed class CR {
is NetworkConfig -> json.encodeToString(networkConfig)
is ContactInfo -> withUser(user, "contact: ${json.encodeToString(contact)}\nconnectionStats: ${json.encodeToString(connectionStats_)}")
is GroupMemberInfo -> withUser(user, "group: ${json.encodeToString(groupInfo)}\nmember: ${json.encodeToString(member)}\nconnectionStats: ${json.encodeToString(connectionStats_)}")
is QueueInfoR -> withUser(user, "rcvMsgInfo: ${json.encodeToString(rcvMsgInfo)}\nqueueInfo: ${json.encodeToString(queueInfo)}\n")
is ContactSwitchStarted -> withUser(user, "contact: ${json.encodeToString(contact)}\nconnectionStats: ${json.encodeToString(connectionStats)}")
is GroupMemberSwitchStarted -> withUser(user, "group: ${json.encodeToString(groupInfo)}\nmember: ${json.encodeToString(member)}\nconnectionStats: ${json.encodeToString(connectionStats)}")
is ContactSwitchAborted -> withUser(user, "contact: ${json.encodeToString(contact)}\nconnectionStats: ${json.encodeToString(connectionStats)}")
@@ -5786,3 +5809,52 @@ enum class UserNetworkType {
OTHER -> generalGetString(MR.strings.network_type_other)
}
}
@Serializable
data class RcvMsgInfo (
val msgId: Long,
val msgDeliveryId: Long,
val msgDeliveryStatus: String,
val agentMsgId: Long,
val agentMsgMeta: String
)
@Serializable
data class QueueInfo (
val qiSnd: Boolean,
val qiNtf: Boolean,
val qiSub: QSub? = null,
val qiSize: Int,
val qiMsg: MsgInfo? = null
)
@Serializable
data class QSub (
val qSubThread: QSubThread,
val qDelivered: String? = null
)
enum class QSubThread {
@SerialName("noSub")
NO_SUB,
@SerialName("subPending")
SUB_PENDING,
@SerialName("subThread")
SUB_THREAD,
@SerialName("prohibitSub")
PROHIBIT_SUB
}
@Serializable
data class MsgInfo (
val msgId: String,
val msgTs: Instant,
val msgType: MsgType,
)
enum class MsgType {
@SerialName("message")
MESSAGE,
@SerialName("quota")
QUOTA
}
@@ -42,6 +42,7 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import kotlinx.datetime.Clock
import kotlinx.serialization.encodeToString
import java.io.File
@Composable
@@ -418,6 +419,19 @@ fun ChatInfoLayout(
SectionView(title = stringResource(MR.strings.section_title_for_console)) {
InfoRow(stringResource(MR.strings.info_row_local_name), chat.chatInfo.localDisplayName)
InfoRow(stringResource(MR.strings.info_row_database_id), chat.chatInfo.apiId.toString())
SectionItemView({
withBGApi {
val info = controller.apiContactQueueInfo(chat.remoteHostId, chat.chatInfo.apiId)
if (info != null) {
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.message_queue_info),
text = queueInfoText(info)
)
}
}
}) {
Text(stringResource(MR.strings.info_row_debug_delivery))
}
}
}
SectionBottomSpacer()
@@ -798,6 +812,12 @@ fun showSyncConnectionForceAlert(syncConnectionForce: () -> Unit) {
)
}
fun queueInfoText(info: Pair<RcvMsgInfo?, QueueInfo>): String {
val (rcvMsgInfo, qInfo) = info
val msgInfo: String = if (rcvMsgInfo != null) json.encodeToString(rcvMsgInfo) else generalGetString(MR.strings.message_queue_info_none)
return generalGetString(MR.strings.message_queue_info_server_info).format(json.encodeToString(qInfo), msgInfo)
}
@Preview
@Composable
fun PreviewChatInfoLayout() {
@@ -3,6 +3,7 @@ package chat.simplex.common.views.chat.group
import InfoRow
import SectionBottomSpacer
import SectionDividerSpaced
import SectionItemView
import SectionSpacer
import SectionTextFooter
import SectionView
@@ -27,6 +28,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import chat.simplex.common.model.*
import chat.simplex.common.model.ChatModel.controller
import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.chat.*
import chat.simplex.common.views.helpers.*
@@ -58,6 +60,7 @@ fun GroupMemberInfoView(
if (chat != null) {
val newRole = remember { mutableStateOf(member.memberRole) }
GroupMemberInfoLayout(
rhId = rhId,
groupInfo,
member,
connStats,
@@ -219,6 +222,7 @@ fun removeMemberDialog(rhId: Long?, groupInfo: GroupInfo, member: GroupMember, c
@Composable
fun GroupMemberInfoLayout(
rhId: Long?,
groupInfo: GroupInfo,
member: GroupMember,
connStats: MutableState<ConnectionStats?>,
@@ -397,6 +401,19 @@ fun GroupMemberInfoLayout(
SectionView(title = stringResource(MR.strings.section_title_for_console)) {
InfoRow(stringResource(MR.strings.info_row_local_name), member.localDisplayName)
InfoRow(stringResource(MR.strings.info_row_database_id), member.groupMemberId.toString())
SectionItemView({
withBGApi {
val info = controller.apiGroupMemberQueueInfo(rhId, groupInfo.apiId, member.groupMemberId)
if (info != null) {
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.message_queue_info),
text = queueInfoText(info)
)
}
}
}) {
Text(stringResource(MR.strings.info_row_debug_delivery))
}
}
}
SectionBottomSpacer()
@@ -644,6 +661,7 @@ fun blockMemberForAll(rhId: Long?, gInfo: GroupInfo, member: GroupMember, blocke
fun PreviewGroupMemberInfoLayout() {
SimpleXTheme {
GroupMemberInfoLayout(
rhId = null,
groupInfo = GroupInfo.sampleData,
member = GroupMember.sampleData,
connStats = remember { mutableStateOf(null) },
@@ -1401,6 +1401,7 @@
<string name="section_title_for_console">FOR CONSOLE</string>
<string name="info_row_local_name">Local name</string>
<string name="info_row_database_id">Database ID</string>
<string name="info_row_debug_delivery">Debug delivery</string>
<string name="info_row_updated_at">Record updated at</string>
<string name="info_row_sent_at">Sent at</string>
<string name="info_row_created_at">Created at</string>
@@ -1462,6 +1463,9 @@
<string name="info_row_connection">Connection</string>
<string name="conn_level_desc_direct">direct</string>
<string name="conn_level_desc_indirect">indirect (%1$s)</string>
<string name="message_queue_info">Message queue info</string>
<string name="message_queue_info_none">none</string>
<string name="message_queue_info_server_info">server queue info: %1$s\n\nlast received msg: %2$s</string>
<!-- GroupWelcomeView.kt -->
<string name="group_welcome_title">Welcome message</string>