From 2b1ccd653ad75bd2d56ecbb549aa3895f738d56e Mon Sep 17 00:00:00 2001 From: James Rich Date: Wed, 13 May 2026 12:19:22 -0500 Subject: [PATCH] fix: break Koin circular dependency with Lazy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MeshConnectionManagerImpl and LockdownCoordinatorImpl constructor-inject each other, causing a StackOverflowError at Koin resolution time. The coordinator only needs MeshConnectionManager in two rare paths (lock-now-ack and post-unlock config reload), so defer its resolution with Lazy — matching the existing Lazy pattern in FromRadioPacketHandlerImpl. --- .../meshtastic/core/data/manager/LockdownCoordinatorImpl.kt | 6 +++--- .../core/data/manager/FromRadioPacketHandlerImplTest.kt | 2 +- .../core/data/manager/LockdownCoordinatorImplTest.kt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/LockdownCoordinatorImpl.kt b/core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/LockdownCoordinatorImpl.kt index a39ac63b9..179d14496 100644 --- a/core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/LockdownCoordinatorImpl.kt +++ b/core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/LockdownCoordinatorImpl.kt @@ -44,7 +44,7 @@ class LockdownCoordinatorImpl( private val commandSender: CommandSender, private val passphraseStore: LockdownPassphraseStore, private val radioInterfaceService: RadioInterfaceService, - private val connectionManager: MeshConnectionManager, + private val connectionManager: Lazy, ) : LockdownCoordinator { @Volatile private var wasAutoAttempt = false @@ -86,7 +86,7 @@ class LockdownCoordinatorImpl( Logger.i { "Lockdown: Lock Now acknowledged — resetting session authorization" } serviceRepository.setSessionAuthorized(false) resetTransientState() - connectionManager.clearRadioConfig() + connectionManager.value.clearRadioConfig() serviceRepository.setLockdownState(LockdownState.LockNowAcknowledged) } @@ -141,7 +141,7 @@ class LockdownCoordinatorImpl( ) serviceRepository.setLockdownState(LockdownState.Unlocked) serviceRepository.setSessionAuthorized(true) - connectionManager.startConfigOnly() + connectionManager.value.startConfigOnly() } @Suppress("TooGenericExceptionCaught") diff --git a/core/data/src/commonTest/kotlin/org/meshtastic/core/data/manager/FromRadioPacketHandlerImplTest.kt b/core/data/src/commonTest/kotlin/org/meshtastic/core/data/manager/FromRadioPacketHandlerImplTest.kt index e289af92a..89d711866 100644 --- a/core/data/src/commonTest/kotlin/org/meshtastic/core/data/manager/FromRadioPacketHandlerImplTest.kt +++ b/core/data/src/commonTest/kotlin/org/meshtastic/core/data/manager/FromRadioPacketHandlerImplTest.kt @@ -34,6 +34,7 @@ import org.meshtastic.proto.ClientNotification import org.meshtastic.proto.Config import org.meshtastic.proto.DeviceMetadata import org.meshtastic.proto.FromRadio +import org.meshtastic.proto.LockdownStatus import org.meshtastic.proto.ModuleConfig import org.meshtastic.proto.MqttClientProxyMessage import org.meshtastic.proto.MyNodeInfo @@ -42,7 +43,6 @@ import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue -import org.meshtastic.proto.LockdownStatus import org.meshtastic.proto.NodeInfo as ProtoNodeInfo class FromRadioPacketHandlerImplTest { diff --git a/core/data/src/commonTest/kotlin/org/meshtastic/core/data/manager/LockdownCoordinatorImplTest.kt b/core/data/src/commonTest/kotlin/org/meshtastic/core/data/manager/LockdownCoordinatorImplTest.kt index 2f681eaa9..07d5412a6 100644 --- a/core/data/src/commonTest/kotlin/org/meshtastic/core/data/manager/LockdownCoordinatorImplTest.kt +++ b/core/data/src/commonTest/kotlin/org/meshtastic/core/data/manager/LockdownCoordinatorImplTest.kt @@ -151,7 +151,7 @@ class LockdownCoordinatorImplTest { commandSender = commandSender, passphraseStore = passphraseStore, radioInterfaceService = radioService, - connectionManager = connectionManager, + connectionManager = lazy { connectionManager }, ) private val testDeviceAddress = "AA:BB:CC:DD:EE:FF"