Skip to content

Commit

Permalink
Refactor/More proper use of DI for Synchronizer (#7500)
Browse files Browse the repository at this point in the history
Co-authored-by: Lukasz Rozmej <lukasz.rozmej@gmail.com>
Co-authored-by: Alex <alexb5dh@gmail.com>
  • Loading branch information
3 people authored Oct 16, 2024
1 parent 31c5131 commit ae3e7a6
Show file tree
Hide file tree
Showing 40 changed files with 911 additions and 749 deletions.
3 changes: 3 additions & 0 deletions src/Nethermind/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
<PackageVersion Include="AspNetCore.HealthChecks.UI" Version="8.0.1" />
<PackageVersion Include="AspNetCore.HealthChecks.UI.Client" Version="8.0.1" />
<PackageVersion Include="AspNetCore.HealthChecks.UI.InMemory.Storage" Version="8.0.1" />
<PackageVersion Include="Autofac" Version="8.1.0" />
<PackageVersion Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
<PackageVersion Include="BenchmarkDotNet" Version="0.13.12" />
<PackageVersion Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.13.12" />
<PackageVersion Include="BouncyCastle.Cryptography" Version="2.4.0" />
Expand Down Expand Up @@ -36,6 +38,7 @@
<PackageVersion Include="Microsoft.ClearScript.V8.Native.osx-x64" Version="7.4.5" />
<PackageVersion Include="Microsoft.ClearScript.V8.Native.win-x64" Version="7.4.5" />
<PackageVersion Include="McMaster.Extensions.CommandLineUtils" Version="4.1.1" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
Expand Down
8 changes: 8 additions & 0 deletions src/Nethermind/Nethermind.Api/IApiWithBlockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: LGPL-3.0-only

#nullable enable
using Autofac;
using Nethermind.Blockchain;
using Nethermind.Blockchain.Filters;
using Nethermind.Blockchain.FullPruning;
Expand Down Expand Up @@ -100,5 +101,12 @@ public interface IApiWithBlockchain : IApiWithStores, IBlockchainBridgeFactory
INodeStorageFactory NodeStorageFactory { get; set; }
BackgroundTaskScheduler BackgroundTaskScheduler { get; set; }
CensorshipDetector CensorshipDetector { get; set; }

public ContainerBuilder ConfigureContainerBuilderFromApiWithBlockchain(ContainerBuilder builder)
{
return ConfigureContainerBuilderFromApiWithStores(builder)
.AddPropertiesFrom<IApiWithBlockchain>(this)
.AddSingleton<INodeStorage>(NodeStorageFactory.WrapKeyValueStore(DbProvider!.StateDb));
}
}
}
15 changes: 14 additions & 1 deletion src/Nethermind/Nethermind.Api/IApiWithNetwork.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
// SPDX-License-Identifier: LGPL-3.0-only

using System.Collections.Generic;
using Autofac;
using Nethermind.Consensus;
using Nethermind.Core;
using Nethermind.Core.PubSub;
using Nethermind.Grpc;
using Nethermind.JsonRpc;
Expand All @@ -16,6 +18,7 @@
using Nethermind.Synchronization;
using Nethermind.Synchronization.Peers;
using Nethermind.Sockets;
using Nethermind.Synchronization.ParallelSync;

namespace Nethermind.Api
{
Expand All @@ -41,12 +44,22 @@ public interface IApiWithNetwork : IApiWithBlockchain
IJsonRpcLocalStats? JsonRpcLocalStats { get; set; }
ISessionMonitor? SessionMonitor { get; set; }
IStaticNodesManager? StaticNodesManager { get; set; }
ISynchronizer? Synchronizer { get; set; }
ISynchronizer? Synchronizer { get; }
ISyncModeSelector SyncModeSelector { get; }
ISyncProgressResolver? SyncProgressResolver { get; }
IPivot? Pivot { get; set; }
ISyncPeerPool? SyncPeerPool { get; set; }
IPeerDifficultyRefreshPool? PeerDifficultyRefreshPool { get; set; }
ISyncServer? SyncServer { get; set; }
IWebSocketsManager WebSocketsManager { get; set; }
ISubscriptionFactory? SubscriptionFactory { get; set; }

IContainer? ApiWithNetworkServiceContainer { get; set; }

public ContainerBuilder ConfigureContainerBuilderFromApiWithNetwork(ContainerBuilder builder)
{
return ConfigureContainerBuilderFromApiWithBlockchain(builder)
.AddPropertiesFrom<IApiWithNetwork>(this);
}
}
}
8 changes: 8 additions & 0 deletions src/Nethermind/Nethermind.Api/IApiWithStores.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using Autofac;
using Nethermind.Blockchain;
using Nethermind.Blockchain.Blocks;
using Nethermind.Blockchain.Find;
using Nethermind.Blockchain.Receipts;
using Nethermind.Consensus;
using Nethermind.Core;
using Nethermind.Crypto;
using Nethermind.Db.Blooms;
using Nethermind.Facade.Find;
Expand All @@ -30,5 +32,11 @@ public interface IApiWithStores : IBasicApi
IReceiptMonitor? ReceiptMonitor { get; set; }
IWallet? Wallet { get; set; }
IBlockStore? BadBlocksStore { get; set; }

public ContainerBuilder ConfigureContainerBuilderFromApiWithStores(ContainerBuilder builder)
{
return ConfigureContainerBuilderFromBasicApi(builder)
.AddPropertiesFrom<IApiWithStores>(this);
}
}
}
18 changes: 15 additions & 3 deletions src/Nethermind/Nethermind.Api/IBasicApi.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Collections.Generic;
using System.IO.Abstractions;
using System.Linq;
using Autofac;
using Nethermind.Abi;
using Nethermind.Api.Extensions;
using Nethermind.Blockchain.Synchronization;
using Nethermind.Config;
using Nethermind.Core;
using Nethermind.Core.Specs;
Expand All @@ -17,7 +20,6 @@
using Nethermind.Serialization.Json;
using Nethermind.Specs.ChainSpecStyle;
using Nethermind.Synchronization;
using Nethermind.Synchronization.ParallelSync;

namespace Nethermind.Api
{
Expand All @@ -38,10 +40,9 @@ public interface IBasicApi
ILogManager LogManager { get; set; }
ProtectedPrivateKey? OriginalSignerKey { get; set; }
IReadOnlyList<INethermindPlugin> Plugins { get; }
[SkipServiceCollection]
string SealEngineType { get; set; }
ISpecProvider? SpecProvider { get; set; }
ISyncModeSelector SyncModeSelector { get; set; }
ISyncProgressResolver? SyncProgressResolver { get; set; }
IBetterPeerStrategy? BetterPeerStrategy { get; set; }
ITimestamper Timestamper { get; }
ITimerFactory TimerFactory { get; }
Expand All @@ -57,5 +58,16 @@ public IEnumerable<IConsensusWrapperPlugin> GetConsensusWrapperPlugins() =>

public IEnumerable<ISynchronizationPlugin> GetSynchronizationPlugins() =>
Plugins.OfType<ISynchronizationPlugin>();

public ContainerBuilder ConfigureContainerBuilderFromBasicApi(ContainerBuilder builder)
{
builder
.AddPropertiesFrom<IBasicApi>(this)
.AddSingleton(ConfigProvider.GetConfig<ISyncConfig>());

DbProvider!.ConfigureServiceCollection(builder);

return builder;
}
}
}
9 changes: 6 additions & 3 deletions src/Nethermind/Nethermind.Api/NethermindApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Collections.Generic;
using System.IO.Abstractions;
using Autofac;
using Nethermind.Abi;
using Nethermind.Api.Extensions;
using Nethermind.Blockchain;
Expand Down Expand Up @@ -186,14 +187,14 @@ public ISealEngine SealEngine
public ISessionMonitor? SessionMonitor { get; set; }
public ISpecProvider? SpecProvider { get; set; }
public IPoSSwitcher PoSSwitcher { get; set; } = NoPoS.Instance;
public ISyncModeSelector SyncModeSelector { get; set; } = null!;
public ISyncModeSelector SyncModeSelector => ApiWithNetworkServiceContainer?.Resolve<ISyncModeSelector>()!;

public ISyncProgressResolver? SyncProgressResolver { get; set; }
public ISyncProgressResolver? SyncProgressResolver => ApiWithNetworkServiceContainer?.Resolve<ISyncProgressResolver>();
public IBetterPeerStrategy? BetterPeerStrategy { get; set; }
public IPivot? Pivot { get; set; }
public ISyncPeerPool? SyncPeerPool { get; set; }
public IPeerDifficultyRefreshPool? PeerDifficultyRefreshPool { get; set; }
public ISynchronizer? Synchronizer { get; set; }
public ISynchronizer? Synchronizer => ApiWithNetworkServiceContainer?.Resolve<ISynchronizer>();
public ISyncServer? SyncServer { get; set; }
public IWorldState? WorldState { get; set; }
public IReadOnlyStateProvider? ChainHeadStateProvider { get; set; }
Expand Down Expand Up @@ -243,5 +244,7 @@ public ISealEngine SealEngine
public CompositePruningTrigger PruningTrigger { get; } = new();
public IProcessExitSource? ProcessExit { get; set; }
public CompositeTxGossipPolicy TxGossipPolicy { get; } = new();

public IContainer? ApiWithNetworkServiceContainer { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,7 @@ public interface ISyncConfig : IConfig

[ConfigItem(Description = "_Technical._ MultiSyncModeSelector sync mode timer loop interval. Used for testing.", DefaultValue = "1000", HiddenFromDocs = true)]
int MultiSyncModeSelectorLoopTimerMs { get; set; }

[ConfigItem(Description = "_Technical._ MultiSyncModeSelector will wait for header to completely sync first.", DefaultValue = "false", HiddenFromDocs = true)]
bool NeedToWaitForHeader { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public string? PivotHash
public int MallocTrimIntervalSec { get; set; } = 300;
public bool? SnapServingEnabled { get; set; } = null;
public int MultiSyncModeSelectorLoopTimerMs { get; set; } = 1000;
public bool NeedToWaitForHeader { get; set; }
public bool TrieHealing { get; set; } = true;

public override string ToString()
Expand Down
113 changes: 113 additions & 0 deletions src/Nethermind/Nethermind.Core.Test/ContainerBuilderExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using Autofac;
using FluentAssertions;
using NUnit.Framework;

namespace Nethermind.Core.Test;

public class ContainerBuilderExtensionsTests
{
[Test]
public void AddPropertiesFrom_CanAddProperties()
{
ITestInterface interfaceImplementation = new InterfaceImplementation();
IContainer sp = new ContainerBuilder()
.AddPropertiesFrom(interfaceImplementation)
.Build();

sp.ResolveOptional<DeclaredService>().Should().NotBeNull();
sp.ResolveOptional<DeclaredInBase>().Should().BeNull();
sp.ResolveOptional<Ignored>().Should().BeNull();
sp.ResolveOptional<DeclaredButNullService>().Should().BeNull();
}

[Test]
public void TestRegisterNamedComponent()
{
IContainer sp = new ContainerBuilder()
.AddScoped<MainComponent>()
.AddScoped<MainComponentDependency>()
.RegisterNamedComponentInItsOwnLifetime<MainComponent>("custom", cfg =>
{
// Override it in custom
cfg.AddScoped<MainComponentDependency, MainComponentDependencySubClass>();
})
.Build();

using (ILifetimeScope scope = sp.BeginLifetimeScope())
{
scope.Resolve<MainComponent>().Property.Should().BeOfType<MainComponentDependency>();
}

MainComponentDependency customMainComponentDependency = sp.ResolveNamed<MainComponent>("custom").Property;
sp.ResolveNamed<MainComponent>("custom").Property.Should().BeOfType<MainComponentDependencySubClass>();

sp.Dispose();

customMainComponentDependency.WasDisposed.Should().BeTrue();
}

private class MainComponent(MainComponentDependency mainComponentDependency, ILifetimeScope scope) : IDisposable
{
public MainComponentDependency Property => mainComponentDependency;

public void Dispose()
{
scope.Dispose();
}
}

private class MainComponentDependency : IDisposable
{
public bool WasDisposed { get; set; }

public void Dispose()
{
WasDisposed = true;
}
}

private class MainComponentDependencySubClass : MainComponentDependency
{
}

private class InterfaceImplementation : ITestInterface
{
public DeclaredService TheService { get; set; } = new DeclaredService();
public DeclaredButNullService? NullService { get; set; } = null;
public Ignored IgnoredService { get; set; } = new Ignored();
public DeclaredInBase BaseService { get; set; } = new DeclaredInBase();
}

private interface ITestInterface : ITestInterfaceBase
{
DeclaredService TheService { get; set; }
DeclaredButNullService? NullService { get; set; }

[SkipServiceCollection]
Ignored IgnoredService { get; set; }
}

private interface ITestInterfaceBase
{
DeclaredInBase BaseService { get; set; }
}

private class DeclaredInBase { }
private class DeclaredService { }
private class DeclaredButNullService { }
private class Ignored { }

private class DisposableService : IDisposable
{
public bool WasDisposed { get; set; } = false;

public void Dispose()
{
WasDisposed = true;
}
}
}
Loading

0 comments on commit ae3e7a6

Please sign in to comment.