From 1bafa8aad2de522f7e8e6f59fd4f9e060004f5e8 Mon Sep 17 00:00:00 2001 From: ogabrielluiz Date: Thu, 25 Jun 2026 12:15:26 -0300 Subject: [PATCH] fix(lfx): reset factory-registered flag on ServiceManager teardown teardown() emptied self.factories but left factory_registered set, so get_service()'s lazy re-registration was skipped and later lookups raised NoFactoryRegisteredError. Once Graph.arun started routing through the executor service, that surfaced as intermittent flow-execution 500s in the backend unit suite whenever a sibling test had torn the global manager down. --- src/lfx/src/lfx/services/manager.py | 6 ++++++ .../unit/services/test_service_manager.py | 21 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/lfx/src/lfx/services/manager.py b/src/lfx/src/lfx/services/manager.py index 2401ac7d91..e07c947b1e 100644 --- a/src/lfx/src/lfx/services/manager.py +++ b/src/lfx/src/lfx/services/manager.py @@ -306,6 +306,12 @@ class ServiceManager: self.services = {} self.factories = {} + # ``teardown`` empties the factory registry, so the "registered" flag has + # to drop too: get_service() re-registers factories only when + # are_factories_registered() is False. Leaving it set after a teardown + # makes the next lookup skip re-registration and raise + # NoFactoryRegisteredError. + self.factory_registered = False @classmethod def get_factories(cls) -> list[ServiceFactory]: diff --git a/src/lfx/tests/unit/services/test_service_manager.py b/src/lfx/tests/unit/services/test_service_manager.py index c1b4e8b11b..a440f30634 100644 --- a/src/lfx/tests/unit/services/test_service_manager.py +++ b/src/lfx/tests/unit/services/test_service_manager.py @@ -359,6 +359,27 @@ class TestTeardown: # Services should be cleared assert ServiceType.STORAGE_SERVICE not in service_manager.services + @pytest.mark.asyncio + async def test_teardown_clears_factories_registered_flag(self, service_manager): + """teardown() must clear the factories-registered flag, not just the dict. + + get_service() (both lfx and langflow) re-registers factories only when + are_factories_registered() returns False. teardown() empties + self.factories, so if it leaves the flag set, every later lookup skips + re-registration and raises NoFactoryRegisteredError. That surfaced as + flow-execution 500s once Graph.arun routed through the executor service + and a sibling test had torn the global manager down. + """ + service_manager.register_service_class(ServiceType.STORAGE_SERVICE, LocalStorageService) + service_manager.get(ServiceType.STORAGE_SERVICE) + service_manager.set_factory_registered() + assert service_manager.are_factories_registered() is True + + await service_manager.teardown() + + assert service_manager.factories == {} + assert service_manager.are_factories_registered() is False + class TestConfigDirectorySource: """Tests for config_dir parameter with real services."""