Skip to content

Commit

Permalink
feat: 缓慢查询
Browse files Browse the repository at this point in the history
  • Loading branch information
lisonge committed Feb 6, 2024
1 parent 3f91b7f commit 3034c6a
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 5 deletions.
4 changes: 2 additions & 2 deletions app/src/main/kotlin/li/songe/gkd/data/RawSubscription.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
13 changes: 12 additions & 1 deletion app/src/main/kotlin/li/songe/gkd/data/ResolvedRule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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) }
Expand All @@ -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
Expand Down
146 changes: 146 additions & 0 deletions app/src/main/kotlin/li/songe/gkd/ui/SlowGroupPage.kt
Original file line number Diff line number Diff line change
@@ -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
)
}
}
31 changes: 31 additions & 0 deletions app/src/main/kotlin/li/songe/gkd/ui/home/ControlPage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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()
Expand Down Expand Up @@ -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()
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/kotlin/li/songe/gkd/util/SubsState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
5 changes: 3 additions & 2 deletions selector/src/commonMain/kotlin/li/songe/selector/Selector.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down

0 comments on commit 3034c6a

Please sign in to comment.