Skip to content

Commit 2565707

Browse files
committed
Scope down changes to the smallest fix.
1 parent 731c74e commit 2565707

File tree

4 files changed

+1
-163
lines changed

4 files changed

+1
-163
lines changed

src/Components/Server/src/Circuits/CircuitHost.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -687,8 +687,6 @@ private void AssertInitialized()
687687
}
688688
}
689689

690-
internal bool IsDisposed() => _disposed;
691-
692690
private void AssertNotDisposed()
693691
{
694692
#pragma warning disable CA1513 // Use ObjectDisposedException throw helper

src/Components/Server/src/Circuits/CircuitPersistenceManager.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@ public async Task PauseCircuitAsync(CircuitHost circuit, bool saveStateToClient
2323
{
2424
await circuit.Renderer.Dispatcher.InvokeAsync(async () =>
2525
{
26-
if (circuit.IsDisposed())
27-
{
28-
return;
29-
}
30-
3126
var renderer = circuit.Renderer;
3227
var persistenceManager = circuit.Services.GetRequiredService<ComponentStatePersistenceManager>();
3328
var collector = new CircuitPersistenceManagerCollector(circuitOptions, serverComponentSerializer, circuit.Renderer);

src/Components/Server/src/Circuits/CircuitRegistry.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ private Task PauseAndDisposeCircuitEntry(DisconnectedCircuitEntry entry)
307307
return Task.CompletedTask;
308308
}
309309

310-
internal async Task PauseAndDisposeCircuitHost(CircuitHost circuitHost, bool saveStateToClient)
310+
private async Task PauseAndDisposeCircuitHost(CircuitHost circuitHost, bool saveStateToClient)
311311
{
312312
await _circuitPersistenceManager.PauseCircuitAsync(circuitHost, saveStateToClient);
313313
circuitHost.UnhandledException -= CircuitHost_UnhandledException;

src/Components/Server/test/Circuits/CircuitRegistryTest.cs

Lines changed: 0 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -620,17 +620,6 @@ protected override void OnEntryEvicted(object key, object value, EvictionReason
620620
base.OnEntryEvicted(key, value, reason, state);
621621
OnAfterEntryEvicted?.Invoke();
622622
}
623-
624-
public void TriggerEviction(object key, object value, EvictionReason reason)
625-
{
626-
OnEntryEvicted(key, value, reason, null);
627-
}
628-
629-
public async Task SimulateEvictionAndDispose(CircuitHost circuitHost)
630-
{
631-
// Directly call PauseAndDisposeCircuitHost which is what eviction does
632-
await PauseAndDisposeCircuitHost(circuitHost, saveStateToClient: false);
633-
}
634623
}
635624

636625
private class TestCircuitPersistenceProvider : ICircuitPersistenceProvider
@@ -689,148 +678,4 @@ private static (CircuitRegistry Registry, TestCircuitPersistenceProvider Provide
689678
persistenceManager);
690679
return (registry, provider);
691680
}
692-
693-
[Fact]
694-
public async Task PauseAfterTermination_DoesNotThrow()
695-
{
696-
var circuitIdFactory = TestCircuitIdFactory.CreateTestFactory();
697-
var options = new CircuitOptions();
698-
699-
var circuitHost = new TestCircuitHostForRaceConditions(
700-
circuitIdFactory.CreateCircuitId(),
701-
CreateServiceScope(),
702-
options);
703-
704-
var persistenceProvider = new TestCircuitPersistenceProvider();
705-
var registry = new TestCircuitRegistry(circuitIdFactory, options, persistenceProvider);
706-
registry.Register(circuitHost);
707-
708-
// First terminate the circuit - it calls circuitHost.DisposeAsync()
709-
await registry.TerminateAsync(circuitHost.CircuitId);
710-
711-
// Then try to pause - it will try to resolve services from the DI scope that is already disposed
712-
await registry.PauseAndDisposeCircuitHost(circuitHost, saveStateToClient: true);
713-
}
714-
715-
[Fact]
716-
public async Task MultiplePause_DoesNotThrow()
717-
{
718-
var circuitIdFactory = TestCircuitIdFactory.CreateTestFactory();
719-
var options = new CircuitOptions();
720-
721-
var circuitHost = new TestCircuitHostForRaceConditions(
722-
circuitIdFactory.CreateCircuitId(),
723-
CreateServiceScope(),
724-
options);
725-
726-
var persistenceProvider = new TestCircuitPersistenceProvider();
727-
var registry = new TestCircuitRegistry(circuitIdFactory, options, persistenceProvider);
728-
registry.Register(circuitHost);
729-
730-
// First pause should be successful
731-
await registry.PauseAndDisposeCircuitHost(circuitHost, saveStateToClient: true);
732-
733-
// Second pause - it will try to resolve services from the DI scope that is already disposed
734-
await registry.PauseAndDisposeCircuitHost(circuitHost, saveStateToClient: true);
735-
}
736-
737-
[Fact]
738-
public async Task PauseAfterEviction_DoesNotThrow()
739-
{
740-
var circuitIdFactory = TestCircuitIdFactory.CreateTestFactory();
741-
var options = new CircuitOptions();
742-
743-
var circuitHost = new TestCircuitHostForRaceConditions(
744-
circuitIdFactory.CreateCircuitId(),
745-
CreateServiceScope(),
746-
options);
747-
748-
var persistenceProvider = new TestCircuitPersistenceProvider();
749-
var registry = new TestCircuitRegistry(circuitIdFactory, options, persistenceProvider);
750-
registry.Register(circuitHost);
751-
752-
// First simulate eviction by calling the same method that eviction calls
753-
await registry.SimulateEvictionAndDispose(circuitHost);
754-
755-
// Then try to pause - it will try to resolve services from the DI scope that is already disposed
756-
await registry.PauseAndDisposeCircuitHost(circuitHost, saveStateToClient: true);
757-
}
758-
759-
[Fact]
760-
public async Task EvictionAndTermination_DoesNotThrow()
761-
{
762-
var circuitIdFactory = TestCircuitIdFactory.CreateTestFactory();
763-
var options = new CircuitOptions();
764-
765-
var circuitHost = new TestCircuitHostForRaceConditions(
766-
circuitIdFactory.CreateCircuitId(),
767-
CreateServiceScope(),
768-
options);
769-
770-
var persistenceProvider = new TestCircuitPersistenceProvider();
771-
var registry = new TestCircuitRegistry(circuitIdFactory, options, persistenceProvider);
772-
registry.Register(circuitHost);
773-
774-
// We never observed any issues with eviction and termination
775-
await registry.SimulateEvictionAndDispose(circuitHost);
776-
await registry.TerminateAsync(circuitHost.CircuitId);
777-
}
778-
779-
private static AsyncServiceScope CreateServiceScope()
780-
{
781-
var serviceCollection = new ServiceCollection();
782-
serviceCollection.AddSingleton(sp => new ComponentStatePersistenceManager(
783-
NullLoggerFactory.Instance.CreateLogger<ComponentStatePersistenceManager>(), sp));
784-
serviceCollection.AddSingleton(sp => sp.GetRequiredService<ComponentStatePersistenceManager>().State);
785-
var serviceProvider = serviceCollection.BuildServiceProvider();
786-
return serviceProvider.CreateAsyncScope();
787-
}
788-
789-
private class TestCircuitHostForRaceConditions : CircuitHost
790-
{
791-
public TestCircuitHostForRaceConditions(
792-
CircuitId circuitId,
793-
AsyncServiceScope scope,
794-
CircuitOptions options)
795-
: base(
796-
circuitId,
797-
scope,
798-
options,
799-
new CircuitClientProxy(Mock.Of<ISingleClientProxy>(), Guid.NewGuid().ToString()),
800-
CreateRemoteRenderer(),
801-
Array.Empty<ComponentDescriptor>(),
802-
new RemoteJSRuntime(Options.Create(new CircuitOptions()), Options.Create(new HubOptions<ComponentHub>()), Mock.Of<ILogger<RemoteJSRuntime>>()),
803-
new RemoteNavigationManager(Mock.Of<ILogger<RemoteNavigationManager>>()),
804-
Array.Empty<CircuitHandler>(),
805-
new CircuitMetrics(new TestMeterFactory()),
806-
new CircuitActivitySource(),
807-
NullLogger<CircuitHost>.Instance)
808-
{
809-
}
810-
811-
private static RemoteRenderer CreateRemoteRenderer()
812-
{
813-
var clientProxy = new CircuitClientProxy(Mock.Of<ISingleClientProxy>(), Guid.NewGuid().ToString());
814-
var jsRuntime = new RemoteJSRuntime(Options.Create(new CircuitOptions()), Options.Create(new HubOptions<ComponentHub>()), Mock.Of<ILogger<RemoteJSRuntime>>());
815-
var componentsActivitySource = new ComponentsActivitySource();
816-
var serviceProvider = new Mock<IServiceProvider>();
817-
serviceProvider
818-
.Setup(services => services.GetService(typeof(IJSRuntime)))
819-
.Returns(jsRuntime);
820-
serviceProvider
821-
.Setup(services => services.GetService(typeof(ComponentsActivitySource)))
822-
.Returns(componentsActivitySource);
823-
var serverComponentDeserializer = Mock.Of<IServerComponentDeserializer>();
824-
825-
return new RemoteRenderer(
826-
serviceProvider.Object,
827-
NullLoggerFactory.Instance,
828-
new CircuitOptions(),
829-
clientProxy,
830-
serverComponentDeserializer,
831-
NullLogger.Instance,
832-
jsRuntime,
833-
new CircuitJSComponentInterop(new CircuitOptions()));
834-
}
835-
}
836681
}

0 commit comments

Comments
 (0)