Skip to content

Commit

Permalink
[ADS-176120] Add RxJavaRuntimeErrorHandler
Browse files Browse the repository at this point in the history
  • Loading branch information
dennisdeng2002 committed Dec 1, 2023
1 parent b5a4d21 commit 03c1169
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import io.reactivex.rxjava3.disposables.FormulaDisposableHelper

object RxJavaRuntime {

private var defaultErrorHandler: ((Throwable) -> Unit)? = null
private var defaultErrorHandler: RxJavaRuntimeErrorHandler? = null

fun setDefaultErrorHandler(handler: ((Throwable) -> Unit)?) {
defaultErrorHandler = handler
fun setDefaultErrorHandler(errorHandler: RxJavaRuntimeErrorHandler?) {
this.defaultErrorHandler = errorHandler
}

fun <Input : Any, Output : Any> start(
Expand All @@ -29,12 +29,20 @@ object RxJavaRuntime {
type = formula.type(),
local = inspector,
)

val onError = { error: Throwable ->
val handled = defaultErrorHandler?.onError(error) ?: false
if (!handled) {
emitter.onError(error)
}
}

val runtimeFactory = {
FormulaRuntime(
threadChecker = threadChecker,
formula = formula,
onOutput = emitter::onNext,
onError = defaultErrorHandler ?: emitter::onError,
onError = onError,
inspector = mergedInspector,
isValidationEnabled = isValidationEnabled,
)
Expand All @@ -52,7 +60,7 @@ object RxJavaRuntime {
runtime = runtimeFactory()
}
runtime.onInput(input)
}, defaultErrorHandler ?: emitter::onError))
}, onError))

val runnable = Runnable {
threadChecker.check("Need to unsubscribe on the main thread.")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.instacart.formula.rxjava3

interface RxJavaRuntimeErrorHandler {
/**
* @param error [Throwable] that occurred
*
* @return true if error was handled, false otherwise
*/
fun onError(error: Throwable): Boolean
}
46 changes: 0 additions & 46 deletions formula/src/test/java/com/instacart/formula/RxJavaRuntimeTest.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.instacart.formula.error

import com.google.common.truth.Truth.assertThat
import com.instacart.formula.Action
import com.instacart.formula.DuplicateKeyException
import com.instacart.formula.internal.ClearPluginsRule
import com.instacart.formula.internal.Try
import com.instacart.formula.rxjava3.RxJavaRuntime
import com.instacart.formula.rxjava3.RxJavaRuntimeErrorHandler
import com.instacart.formula.subjects.DynamicParentFormula
import com.instacart.formula.subjects.OnlyUpdateFormula
import com.instacart.formula.subjects.TestKey
import com.instacart.formula.test.RxJavaTestableRuntime
import com.instacart.formula.test.TestableRuntime
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
import org.junit.rules.TestName
import kotlin.IllegalStateException

class RxJavaRuntimeErrorHandlerTest {

val runtime: TestableRuntime = RxJavaTestableRuntime

@get:Rule
val rule = RuleChain
.outerRule(TestName())
.around(ClearPluginsRule())
.around(runtime.rule)

private val errorLogs = mutableListOf<String>()

private val duplicateKeyErrorHandler = object : RxJavaRuntimeErrorHandler {
override fun onError(error: Throwable): Boolean {
return when (error) {
is DuplicateKeyException -> {
errorLogs.add(error.message.orEmpty())
true
}

else -> {
false
}
}
}
}

@Before
fun setUp() {
RxJavaRuntime.setDefaultErrorHandler(duplicateKeyErrorHandler)
}

@After
fun tearDown() {
RxJavaRuntime.setDefaultErrorHandler(null)
}

@Test
fun `emitting a generic error throws an exception`() {
val result = Try {
val formula = OnlyUpdateFormula<Unit> {
events(Action.onInit()) {
throw IllegalStateException("crashed")
}
}
runtime.test(formula, Unit)
}

val error = result.errorOrNull()?.cause
assertThat(error).isInstanceOf(IllegalStateException::class.java)
assertThat(error?.message).isEqualTo("crashed")

assertThat(errorLogs).isEmpty()
}

@Test
fun `adding duplicate child logs an exception`() {
val result = Try {
val formula = DynamicParentFormula()
runtime.test(formula, Unit)
.output { addChild(TestKey("1")) }
.output { addChild(TestKey("1")) }
}

val error = result.errorOrNull()?.cause
assertThat(error).isNull()
assertThat(errorLogs).hasSize(1)

val log = errorLogs.first()
val expectedLog = "There already is a child with same key: FormulaKey(scopeKey=null, type=class com.instacart.formula.subjects.KeyFormula, key=TestKey(id=1)). Override [Formula.key] function."
assertThat(log).isEqualTo(expectedLog)
}
}

0 comments on commit 03c1169

Please sign in to comment.