Closed
Description
Is there an existing issue?
- I have searched existing issues
Build info
- ObjectBox version: 4.0.3
- OS: Android 13
- Device/ABI/architecture: odroid-m2 | arm64-v8a
Steps to reproduce
I used normal db and test db(both are objectBox).
When changing isTestMode of a single-toned testMode Manager, there is a logic that the dataSource changes accordingly. Before changing, the work related to the db is terminated, but for some reason, a crash occurs.
Expected behavior
Don't occur crash
Actual behavior
Occur crash
Code
Code
@HiltViewModel
class HiddenSettingsViewModel @Inject constructor(
private val stopCcuCommUseCase: StopCcuCommUseCase,
private val testModeManager: TestModeManager,
private val workCcuCommUseCase: WorkCcuCommUseCase,
private val initializeLinkTableItemsUseCase: InitializeLinkTableItemsUseCase,
private val removeTestModeItemsUseCase: RemoveTestModeItemsUseCase,
private val stopTestCcuCommUseCase: StopTestCcuCommUseCase,
private val workTestCcuCommUseCase: WorkTestCcuCommUseCase,
private val stopMakeOutputRequestUseCase: StopMakeOutputRequestUseCase,
private val workMakeOutputRequestUseCase: WorkMakeOutputRequestUseCase
): ViewModel() {
private val _testModeStateFlow = MutableStateFlow(
if (testModeManager.isTestMode) TestModeState.TestMode else TestModeState.NormalMode
)
val testModeStateFlow: StateFlow<TestModeState> = _testModeStateFlow
private val _isTestMode = MutableStateFlow(testModeManager.isTestMode)
val isTestMode: StateFlow<Boolean> = _isTestMode
fun setTestMode(enabled: Boolean) {
viewModelScope.launch {
_testModeStateFlow.value = TestModeState.Loading
try {
stopMakeOutputRequestUseCase()
workMakeOutputRequestUseCase()
if (enabled) {
when (initializeLinkTableItemsUseCase()) {
is LinkTableRepositoryState.Success -> {
stopCcuCommUseCase()
workTestCcuCommUseCase()
_testModeStateFlow.value = TestModeState.TestMode
testModeManager.setTestMode(true)
_isTestMode.value = testModeManager.isTestMode
}
is LinkTableRepositoryState.InsertError -> {
_testModeStateFlow.value = TestModeState.Error
testModeManager.setTestMode(false)
_isTestMode.value = testModeManager.isTestMode
}
}
} else {
stopTestCcuCommUseCase()
removeTestModeItemsUseCase()
workCcuCommUseCase()
_testModeStateFlow.value = TestModeState.NormalMode
testModeManager.setTestMode(false)
_isTestMode.value = testModeManager.isTestMode
}
} catch (e: Exception) {
_testModeStateFlow.value = TestModeState.Error
testModeManager.setTestMode(!enabled)
_isTestMode.value = testModeManager.isTestMode
}
}
}
}
Class CcuCommRepositoryImpl @Inject constructor(
@IoDispatcher private val ioDispatcher: CoroutineDispatcher,
@DefaultDispatcher private val defaultDispatcher: CoroutineDispatcher,
private val allBox: AllBox,
private val repeaterBox: RepeaterBox,
private val detectorBox: DetectorBox,
private val serialPortManager: SerialPortManager
) : CcuCommRepository {
override fun commProcess() {
val serialPort0 = serialPortManager.serialPort0 ?: return
val serialPort1 = serialPortManager.serialPort1 ?: return
val serialPort3 = serialPortManager.serialPort3 ?: return
if (ioScope == null || ioScope?.isActive == false) {
ioScope = CoroutineScope(ioDispatcher + SupervisorJob())
}
if (defaultScope == null || defaultScope?.isActive == false) {
defaultScope = CoroutineScope(defaultDispatcher + SupervisorJob())
}
defaultScope?.let { scope ->
startMakeResponseByte(scope)
workParsing(scope, requestBufferChannels)
}
.
.
.
}
.
.
.
override fun stop() {
ioScope?.cancel()
defaultScope?.cancel()
ioScope = null
defaultScope = null
}
}
class AllBoxImpl @Inject constructor(
@Impermanence private val impermanenceInternalCommBox: Box<InternalCommEntity>,
@Impermanence private val impermanenceStationCommBox: Box<StationCommEntity>,
@Impermanence private val impermanenceStationPowerBox: Box<StationPowerEntity>,
@Impermanence private val impermanenceCcuBox: Box<CcuEntity>,
@Impermanence private val impermanenceDetectorBox: Box<DetectorEntity>,
@Impermanence private val impermanenceRepeaterBox: Box<RepeaterEntity>,
@Impermanence private val impermanenceRepeaterInputBox: Box<RepeaterInputEntity>,
@Impermanence private val impermanenceRepeaterOutputBox: Box<RepeaterOutputEntity>,
@TestMode private val testModeInternalCommBox: Box<InternalCommEntity>,
@TestMode private val testModeStationCommBox: Box<StationCommEntity>,
@TestMode private val testModeStationPowerBox: Box<StationPowerEntity>,
@TestMode private val testModeCcuBox: Box<CcuEntity>,
@TestMode private val testModeDetectorBox: Box<DetectorEntity>,
@TestMode private val testModeRepeaterBox: Box<RepeaterEntity>,
@TestMode private val testModeRepeaterInputBox: Box<RepeaterInputEntity>,
@TestMode private val testModeRepeaterOutputBox: Box<RepeaterOutputEntity>,
private val switchBox: Box<SwitchEntity>,
private val switchBoardBox: Box<SwitchBoardEntity>,
private val pumpBox: Box<PumpEntity>,
private val pumpBoardBox: Box<PumpBoardEntity>,
private val mccRelayBox: Box<MccRelayEntity>,
private val broadcastRelayBox: Box<BroadcastRelayEntity>,
private val ebcBox: Box<EbcEntity>,
private val do24Box: Box<Do24Entity>,
private val tbBox: Box<TbEntity>,
@IoDispatcher private val ioDispatcher: CoroutineDispatcher,
) : AllBox {
private val internalCommQueryByInternalCommIds =
impermanenceInternalCommBox.query().inValues(InternalCommEntity_.internalCommId, longArrayOf()).build()
private val stationPowerQueryByStationId =
impermanenceStationPowerBox.query().inValues(StationPowerEntity_.stationId, longArrayOf()).build()
private val stationCommQueryByStationId =
impermanenceStationCommBox.query().inValues(StationCommEntity_.stationId, longArrayOf()).build()
private val ccuQueryByFullCompositeKeys = impermanenceCcuBox.query().inValues(
CcuEntity_.fullCompositeKey,
arrayOf(), QueryBuilder.StringOrder.CASE_INSENSITIVE
).build()
private val detectorQueryByFullCompositeKeys = impermanenceDetectorBox.query().inValues(
DetectorEntity_.fullCompositeKey,
arrayOf(),
QueryBuilder.StringOrder.CASE_INSENSITIVE
).build()
private val repeaterQueryByFullCompositeKeys = impermanenceRepeaterBox.query().inValues(
RepeaterEntity_.fullCompositeKey,
arrayOf(),
QueryBuilder.StringOrder.CASE_INSENSITIVE
).eager(RepeaterEntity_.inputs).eager(RepeaterEntity_.outputs).build()
override suspend fun addAllInstances(
internalCommInstances: List<InternalCommEntity>,
stationCommInstances: List<StationCommEntity>,
stationPowerInstances: List<StationPowerEntity>,
ccuInstances: List<CcuEntity>,
detectorInstances: List<DetectorEntity>,
repeaterInstances: List<RepeaterEntity>,
repeaterInputInstances: List<RepeaterInputEntity>,
repeaterOutputInstances: List<RepeaterOutputEntity>,
) = withContext(ioDispatcher) {
impermanenceInternalCommBox.store.runInTxAsync({
impermanenceInternalCommBox.put(internalCommInstances)
impermanenceStationCommBox.put(stationCommInstances)
impermanenceStationPowerBox.put(stationPowerInstances)
impermanenceCcuBox.put(ccuInstances)
impermanenceDetectorBox.put(detectorInstances)
impermanenceRepeaterInputBox.put(repeaterInputInstances)
impermanenceRepeaterOutputBox.put(repeaterOutputInstances)
impermanenceRepeaterBox.put(repeaterInstances)
}, null)
impermanenceInternalCommBox.store.closeThreadResources()
}
override suspend fun getAllInstances(
internalCommIds: LongArray,
stationIds: LongArray,
ccuFullCompositeKeys: Array<String>,
deviceFullCompositeKeys: Array<String>,
): AllInstances = withContext(ioDispatcher) {
var result: AllInstances? = null
impermanenceInternalCommBox.store.runInReadTx {
val internalComms = internalCommQueryByInternalCommIds.copy()
.setParameter(InternalCommEntity_.internalCommId, internalCommIds).find()
val stationComms = stationCommQueryByStationId.copy()
.setParameter(StationCommEntity_.stationId, stationIds).find()
val stationPowers = stationPowerQueryByStationId.copy()
.setParameter(StationPowerEntity_.stationId, stationIds).find()
val ccus = ccuQueryByFullCompositeKeys.copy()
.setParameter(CcuEntity_.fullCompositeKey, ccuFullCompositeKeys).find()
val detectors = detectorQueryByFullCompositeKeys.copy()
.setParameter(DetectorEntity_.fullCompositeKey, deviceFullCompositeKeys).find()
val repeaters = repeaterQueryByFullCompositeKeys.copy()
.setParameter(RepeaterEntity_.fullCompositeKey, deviceFullCompositeKeys).find()
result =
AllInstances(internalComms, stationComms, stationPowers, ccus, detectors, repeaters)
}
result ?: throw IllegalStateException("Transaction failed to return result")
}
}
Log
Metadata
Metadata
Assignees
Labels
No labels