feat: 缓慢查询

This commit is contained in:
lisonge 2024-02-06 20:33:15 +08:00
parent 3f91b7fcb6
commit 3034c6aed9
6 changed files with 201 additions and 5 deletions

View File

@ -173,7 +173,7 @@ data class RawSubscription(
}
val allSelectorStrings by lazy {
rules.map { r -> r.matches + (r.excludeMatches ?: emptyList()) }.flatten().distinct()
rules.map { r -> r.matches + (r.excludeMatches ?: emptyList()) }.flatten()
}
val allSelector by lazy {
@ -257,7 +257,7 @@ data class RawSubscription(
) : RawGroupProps, RawAppRuleProps {
val allSelectorStrings by lazy {
rules.map { r -> r.matches + (r.excludeMatches ?: emptyList()) }.flatten().distinct()
rules.map { r -> r.matches + (r.excludeMatches ?: emptyList()) }.flatten()
}
val allSelector by lazy {

View File

@ -16,7 +16,8 @@ sealed class ResolvedRule(
) {
val key = rule.key
val index = group.rules.indexOf(rule)
val preKeys = (rule.preKeys ?: emptyList()).toSet()
val othersKeys = group.rules.filter { r -> r.key != rule.key }.mapNotNull { r -> r.key }.toSet()
val preKeys = (rule.preKeys ?: emptyList()).filter { r -> othersKeys.contains(r) }.toSet()
val resetMatch = rule.resetMatch ?: group.resetMatch
val matches = rule.matches.map { s -> Selector.parse(s) }
val excludeMatches = (rule.excludeMatches ?: emptyList()).map { s -> Selector.parse(s) }
@ -41,6 +42,16 @@ sealed class ResolvedRule(
val order = rule.order ?: group.order ?: 0
val slowSelectors by lazy {
(matches + excludeMatches).filterNot { s ->
((quickFind && s.canQf) || s.isMatchRoot) && !s.connectKeys.contains(
"<<"
)
}
}
val isSlow by lazy { preKeys.isEmpty() && slowSelectors.isNotEmpty() && (matchTime == null || matchTime > 30_000L) }
var groupToRules: Map<out RawSubscription.RawGroupProps, List<ResolvedRule>> = emptyMap()
set(value) {
field = value

View File

@ -0,0 +1,146 @@
package li.songe.gkd.ui
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph
import li.songe.gkd.ui.destinations.AppItemPageDestination
import li.songe.gkd.ui.destinations.GlobalRulePageDestination
import li.songe.gkd.util.LocalNavController
import li.songe.gkd.util.ProfileTransitions
import li.songe.gkd.util.appInfoCacheFlow
import li.songe.gkd.util.navigate
import li.songe.gkd.util.ruleSummaryFlow
@RootNavGraph
@Destination(style = ProfileTransitions::class)
@Composable
fun SlowGroupPage() {
val navController = LocalNavController.current
val ruleSummary by ruleSummaryFlow.collectAsState()
val appInfoCache by appInfoCacheFlow.collectAsState()
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
TopAppBar(
scrollBehavior = scrollBehavior,
navigationIcon = {
IconButton(onClick = {
navController.popBackStack()
}) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = null,
)
}
},
title = { Text(text = if (ruleSummary.slowGroupCount > 0) "缓慢查询-${ruleSummary.slowGroupCount}" else "缓慢查询") },
actions = {}
)
}
) { padding ->
LazyColumn(modifier = Modifier.padding(padding)) {
items(ruleSummary.slowGlobalGroups) { (group, rule) ->
SlowGroupCard(
modifier = Modifier
.clickable {
navController.navigate(
GlobalRulePageDestination(
rule.subsItem.id,
group.key
)
)
}
.padding(10.dp, 5.dp),
title = group.name,
desc = "${rule.rawSubs.name}-全局规则"
)
}
items(ruleSummary.slowAppGroups) { (group, rule) ->
SlowGroupCard(
modifier = Modifier
.clickable {
navController.navigate(
AppItemPageDestination(
rule.subsItem.id,
rule.app.id,
group.key
)
)
}
.padding(10.dp, 5.dp),
title = group.name,
desc = "${rule.rawSubs.name}-应用规则-${appInfoCache[rule.app.id]?.name ?: rule.app.name ?: rule.app.id}"
)
}
item {
Spacer(modifier = Modifier.height(40.dp))
if (ruleSummary.slowGroupCount == 0) {
Text(
text = "暂无规则",
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center
)
}
}
}
}
}
@Composable
fun SlowGroupCard(title: String, desc: String, modifier: Modifier = Modifier) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = modifier,
) {
Column(modifier = Modifier.weight(1f)) {
Text(
text = title, fontSize = 18.sp,
maxLines = 1,
softWrap = false,
overflow = TextOverflow.Ellipsis,
)
Spacer(modifier = Modifier.height(2.dp))
Text(
text = desc, fontSize = 14.sp,
maxLines = 1,
softWrap = false,
overflow = TextOverflow.Ellipsis,
)
}
Icon(
imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight,
contentDescription = null
)
}
}

View File

@ -39,11 +39,13 @@ import li.songe.gkd.service.ManageService
import li.songe.gkd.ui.component.AuthCard
import li.songe.gkd.ui.component.TextSwitch
import li.songe.gkd.ui.destinations.ClickLogPageDestination
import li.songe.gkd.ui.destinations.SlowGroupPageDestination
import li.songe.gkd.util.HOME_PAGE_URL
import li.songe.gkd.util.LocalNavController
import li.songe.gkd.util.checkOrRequestNotifPermission
import li.songe.gkd.util.launchTry
import li.songe.gkd.util.navigate
import li.songe.gkd.util.ruleSummaryFlow
import li.songe.gkd.util.storeFlow
import li.songe.gkd.util.updateStorage
import li.songe.gkd.util.usePollState
@ -58,6 +60,7 @@ fun useControlPage(): ScaffoldExt {
val latestRecordDesc by vm.latestRecordDescFlow.collectAsState()
val subsStatus by vm.subsStatusFlow.collectAsState()
val store by storeFlow.collectAsState()
val ruleSummary by ruleSummaryFlow.collectAsState()
val gkdAccessRunning by GkdAbService.isRunning.collectAsState()
val manageRunning by ManageService.isRunning.collectAsState()
@ -216,6 +219,34 @@ fun useControlPage(): ScaffoldExt {
}
HorizontalDivider()
if (ruleSummary.slowGroupCount > 0) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.clickable {
navController.navigate(SlowGroupPageDestination)
}
.padding(10.dp, 5.dp),
) {
Column(modifier = Modifier.weight(1f)) {
Text(
text = "耗时查询", fontSize = 18.sp
)
Spacer(modifier = Modifier.height(2.dp))
Text(
text = "存在${ruleSummary.slowGroupCount}规则组,可能导致触发缓慢或更多耗电",
fontSize = 14.sp
)
}
Icon(
imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight,
contentDescription = null
)
}
HorizontalDivider()
}
Column(
modifier = Modifier
.fillMaxWidth()

View File

@ -102,6 +102,13 @@ data class RuleSummary(
} else {
"暂无规则"
}
val slowGlobalGroups =
globalRules.filter { r -> r.isSlow }.distinctBy { r -> r.group }.map { r -> r.group to r }
val slowAppGroups =
appIdToRules.values.flatten().filter { r -> r.isSlow }.distinctBy { r -> r.group }
.map { r -> r.group to r }
val slowGroupCount = slowGlobalGroups.size + slowAppGroups.size
}
val ruleSummaryFlow by lazy {

View File

@ -27,8 +27,9 @@ class Selector internal constructor(private val propertyWrapper: PropertyWrapper
var c = propertyWrapper.to
val keys = mutableListOf<String>()
while (c != null) {
c!!.connectSegment.connectExpression
keys.add(c!!.connectSegment.operator.key)
c?.apply {
keys.add(connectSegment.operator.key)
}
c = c?.to?.to
}
keys.toTypedArray()