From a674175131aaa5972e2419cf6d1537371903c8e3 Mon Sep 17 00:00:00 2001 From: Jasper Date: Mon, 8 Jun 2026 10:34:17 +0200 Subject: [PATCH] Making sure every 'SwitchWhen' only subscribes once to every observable. --- ...ansitionPipelineConfigurator.SwitchWhen.cs | 67 +++++++++++++++---- ...htTransitionReactiveNodeConfigurator.On.cs | 2 +- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/src/CodeCasa.AutomationPipelines.Lights/Pipeline/LightTransitionPipelineConfigurator.SwitchWhen.cs b/src/CodeCasa.AutomationPipelines.Lights/Pipeline/LightTransitionPipelineConfigurator.SwitchWhen.cs index bea74e8..1873bce 100644 --- a/src/CodeCasa.AutomationPipelines.Lights/Pipeline/LightTransitionPipelineConfigurator.SwitchWhen.cs +++ b/src/CodeCasa.AutomationPipelines.Lights/Pipeline/LightTransitionPipelineConfigurator.SwitchWhen.cs @@ -139,9 +139,15 @@ public ILightTransitionPipelineConfigurator SwitchWhen(IObservable { return AddReactiveNode(sp => sp .SetHierarchyContext(HierarchyPath, "SwitchWhen", LoggingEnabled ?? false) - .On(whenObservable.Where(x => x).CombineLatest(switchObservable, (_, s) => s).Where(x => x), trueNodeFactory) - .On(whenObservable.Where(x => x).CombineLatest(switchObservable, (_, s) => s).Where(x => !x), falseNodeFactory) - .PassThroughOn(whenObservable.Where(x => !x))); + .AddNodeSource(_ => whenObservable.CombineLatest(switchObservable, (when, sw) => + { + if (!when) + { + return _ => + new PassThroughNode(); + } + return sw ? trueNodeFactory : falseNodeFactory; + }))); } /// @@ -195,9 +201,20 @@ public ILightTransitionPipelineConfigurator SwitchWhen c .SetHierarchyContext(HierarchyPath, "SwitchWhen", LoggingEnabled ?? false) - .On(whenObservable.Where(x => x).CombineLatest(switchObservable, (_, s) => s).Where(x => x)) - .On(whenObservable.Where(x => x).CombineLatest(switchObservable, (_, s) => s).Where(x => !x)) - .PassThroughOn(whenObservable.Where(x => !x))); + .AddNodeSource(_ => whenObservable.CombineLatest(switchObservable, (when, sw) => + { + if (!when) + { + return _ => + new PassThroughNode(); + } + + return sw + ? sp => + ActivatorUtilities.CreateInstance(sp) + : new Func?>(sp => + ActivatorUtilities.CreateInstance(sp)); + }))); } /// @@ -242,9 +259,22 @@ public ILightTransitionPipelineConfigurator AddReactiveNodeSwitchWhen(IO { return AddReactiveNode(c => c .SetHierarchyContext(HierarchyPath, "SwitchWhen", LoggingEnabled ?? false) - .On(whenObservable.Where(x => x).CombineLatest(switchObservable, (_, s) => s).Where(x => x), trueConfigure.ApplyHierarchySettings(c), instantiationScope) - .On(whenObservable.Where(x => x).CombineLatest(switchObservable, (_, s) => s).Where(x => !x), falseConfigure.ApplyHierarchySettings(c), instantiationScope) - .PassThroughOn(whenObservable.Where(x => !x))); + .AddNodeSource(_ => whenObservable.CombineLatest(switchObservable, (when, sw) => + { + if (!when) + { + return _ => + new PassThroughNode(); + } + + return sw + ? new Func?>(sp => sp + .GetRequiredService().CreateReactiveNode(sp, Light, + trueConfigure.ApplyHierarchySettings(HierarchyPath, LoggingEnabled ?? false))) + : new Func?>(sp => sp + .GetRequiredService().CreateReactiveNode(sp, Light, + falseConfigure.ApplyHierarchySettings(HierarchyPath, LoggingEnabled ?? false))); + }))); } /// @@ -280,9 +310,22 @@ public ILightTransitionPipelineConfigurator AddPipelineSwitchWhen(IObser { return AddReactiveNode(c => c .SetHierarchyContext(HierarchyPath, "SwitchWhen", LoggingEnabled ?? false) - .On(whenObservable.Where(x => x).CombineLatest(switchObservable, (_, s) => s).Where(x => x), trueConfigure.ApplyHierarchySettings(c), instantiationScope) - .On(whenObservable.Where(x => x).CombineLatest(switchObservable, (_, s) => s).Where(x => !x), falseConfigure.ApplyHierarchySettings(c), instantiationScope) - .PassThroughOn(whenObservable.Where(x => !x))); + .AddNodeSource(_ => whenObservable.CombineLatest(switchObservable, (when, sw) => + { + if (!when) + { + return _ => + new PassThroughNode(); + } + + return sw + ? new Func?>(sp => sp + .GetRequiredService().CreateLightPipeline(ServiceProvider, Light, + trueConfigure.ApplyHierarchySettings(HierarchyPath, LoggingEnabled ?? false))) + : new Func?>(sp => sp + .GetRequiredService().CreateLightPipeline(ServiceProvider, Light, + falseConfigure.ApplyHierarchySettings(HierarchyPath, LoggingEnabled ?? false))); + }))); } /// diff --git a/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/LightTransitionReactiveNodeConfigurator.On.cs b/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/LightTransitionReactiveNodeConfigurator.On.cs index 87abbcf..6b7ec03 100644 --- a/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/LightTransitionReactiveNodeConfigurator.On.cs +++ b/src/CodeCasa.AutomationPipelines.Lights/ReactiveNode/LightTransitionReactiveNodeConfigurator.On.cs @@ -54,7 +54,7 @@ public ILightTransitionReactiveNodeConfigurator On(IObservable tri public ILightTransitionReactiveNodeConfigurator On(IObservable triggerObservable, Action> configure, InstantiationScope _ = InstantiationScope.Shared) { return On(triggerObservable, - s => s.GetRequiredService().CreateReactiveNode(s, Light, configure.ApplyHierarchySettings(HierarchyPath, LoggingEnabled ?? false))); + sp => sp.GetRequiredService().CreateReactiveNode(sp, Light, configure.ApplyHierarchySettings(HierarchyPath, LoggingEnabled ?? false))); } ///