Skip to content

Commit 9e1fe01

Browse files
committed
Suppress node examiner cancellation noise
- Treat coroutine cancellation as expected node examiner control flow - Keep cancellation out of node_examiner_failed telemetry and circuit-breaker accounting - Add focused coverage for cancellation classification 🤖 Auto-generated
1 parent b1487c6 commit 9e1fe01

2 files changed

Lines changed: 35 additions & 0 deletions

File tree

app/src/main/java/com/enaboapps/switchify/service/techniques/nodes/NodeExaminer.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.enaboapps.switchify.service.keyboard.KeyboardNodeExtractor
1010
import com.enaboapps.switchify.service.utils.ScreenUtils
1111
import com.enaboapps.switchify.utils.LogEvent
1212
import com.enaboapps.switchify.utils.Logger
13+
import kotlinx.coroutines.CancellationException
1314
import kotlinx.coroutines.flow.Flow
1415
import kotlinx.coroutines.flow.MutableSharedFlow
1516
import kotlinx.coroutines.flow.MutableStateFlow
@@ -131,6 +132,7 @@ object NodeExaminer {
131132
}
132133
}
133134
} catch (e: Exception) {
135+
if (isExpectedNodeExaminerCancellation(e)) throw e
134136
val packageName = rootNode?.packageName?.toString()
135137
Log.e(TAG, "Error examining accessibility tree (app=$packageName)", e)
136138
Logger.log(
@@ -147,6 +149,10 @@ object NodeExaminer {
147149
}
148150
}
149151

152+
internal fun isExpectedNodeExaminerCancellation(error: Throwable): Boolean {
153+
return error is CancellationException
154+
}
155+
150156
private fun recordFailure(packageName: String?) {
151157
consecutiveFailures++
152158
if (consecutiveFailures >= CIRCUIT_BREAKER_THRESHOLD) {
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.enaboapps.switchify.service.techniques.nodes
2+
3+
import kotlinx.coroutines.CancellationException
4+
import org.junit.Assert.assertFalse
5+
import org.junit.Assert.assertTrue
6+
import org.junit.Test
7+
8+
class NodeExaminerTest {
9+
@Test
10+
fun cancellationExceptionIsExpectedNodeExaminerCancellation() {
11+
val error = CancellationException("cancelled")
12+
13+
assertTrue(NodeExaminer.isExpectedNodeExaminerCancellation(error))
14+
}
15+
16+
@Test
17+
fun jobCancellationExceptionIsExpectedNodeExaminerCancellation() {
18+
val error = CancellationException("StandaloneCoroutine was cancelled")
19+
20+
assertTrue(NodeExaminer.isExpectedNodeExaminerCancellation(error))
21+
}
22+
23+
@Test
24+
fun ordinaryExceptionIsNotExpectedNodeExaminerCancellation() {
25+
val error = IllegalStateException("failed")
26+
27+
assertFalse(NodeExaminer.isExpectedNodeExaminerCancellation(error))
28+
}
29+
}

0 commit comments

Comments
 (0)