Skip to content

Commit

Permalink
Merge pull request planetarium#3930 from planetarium/exp/sdk/explicit…
Browse files Browse the repository at this point in the history
…-services

Explicit Services Configuration
  • Loading branch information
s2quake authored Aug 27, 2024
2 parents 9b88690 + 5f6ffe1 commit 895c277
Show file tree
Hide file tree
Showing 46 changed files with 183 additions and 447 deletions.
8 changes: 4 additions & 4 deletions sdk/node/Libplanet.Node.Executable/Program.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Libplanet.Node.API.Services;
using Libplanet.Node.Extensions;
using Libplanet.Node.Options.Schema;
using Microsoft.AspNetCore.Server.Kestrel.Core;
Expand All @@ -24,9 +25,7 @@
// Add services to the container.
builder.Services.AddGrpc();
builder.Services.AddGrpcReflection();
var libplanetBuilder = builder.Services.AddLibplanetNode(builder.Configuration)
.WithSwarm()
.WithValidator();
var libplanetBuilder = builder.Services.AddLibplanetNode(builder.Configuration);

var app = builder.Build();
var handlerMessage = """
Expand All @@ -36,7 +35,8 @@ Communication with gRPC endpoints must be made through a gRPC client. To learn h
var schema = await OptionsSchemaBuilder.GetSchemaAsync(default);

// Configure the HTTP request pipeline.
app.MapGrpcServiceFromDomain(libplanetBuilder.Scopes);
app.MapGrpcService<BlockChainGrpcService>();
app.MapGrpcService<SchemaGrpcService>();
app.MapGet("/", () => handlerMessage);
app.MapGet("/schema", () => schema);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
using Grpc.Core;
using Libplanet.Common;
using Libplanet.Node.DependencyInjection;
using Libplanet.Node.Services;
using Libplanet.Types.Blocks;

namespace Libplanet.Node.API.Services;

[Grpc]
public class BlockChainGrpcService(
IReadChainService blockChain)
: BlockChain.BlockChainBase
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
using Grpc.Core;
using Libplanet.Node.DependencyInjection;
using Libplanet.Node.Options;
using Libplanet.Node.Options.Schema;

namespace Libplanet.Node.API.Services;

[Grpc]
public class SchemaGrpcService : Schema.SchemaBase
{
private string[]? _list;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
using Grpc.Core;
using Libplanet.Node.DependencyInjection;
using Libplanet.Node.Services;

namespace Libplanet.Node.API.Services;

[Grpc(Scope = "Seed")]
public class SeedGrpcService(
IServiceProvider serviceProvider)
: Seed.SeedBase
Expand Down
88 changes: 17 additions & 71 deletions sdk/node/Libplanet.Node.Executable/appsettings-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1109,79 +1109,22 @@
}
}
},
"BlocksyncSeed": {
"title": "SeedOptions",
"Solo": {
"title": "SoloOptions",
"type": "object",
"additionalProperties": false,
"properties": {
"PrivateKey": {
"type": "string",
"description": "The private key of the seed node.",
"pattern": "^[0-9a-fA-F]{64}$"
},
"EndPoint": {
"type": "string",
"description": "The endpoint of the seed node.",
"pattern": "^(?:(?:[a-zA-Z0-9\\-\\.]+)|(?:\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})):\\d{1,5}$"
"IsEnabled": {
"type": "boolean"
},
"RefreshInterval": {
"BlockInterval": {
"type": "integer",
"description": "The interval to refresh the peer list.",
"format": "int32",
"maximum": 2147483647.0,
"minimum": 0.0
"format": "int64"
},
"PeerLifetime": {
"type": "integer",
"description": "The lifetime of a peer.",
"format": "int32",
"maximum": 2147483647.0,
"minimum": 0.0
},
"PingTimeout": {
"type": "integer",
"description": "The timeout for a ping.",
"format": "int32",
"maximum": 2147483647.0,
"minimum": 0.0
}
}
},
"ConsensusSeed": {
"title": "SeedOptions",
"type": "object",
"additionalProperties": false,
"properties": {
"PrivateKey": {
"type": "string",
"description": "The private key of the seed node.",
"description": "The private key of the node.",
"pattern": "^[0-9a-fA-F]{64}$"
},
"EndPoint": {
"type": "string",
"description": "The endpoint of the seed node.",
"pattern": "^(?:(?:[a-zA-Z0-9\\-\\.]+)|(?:\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})):\\d{1,5}$"
},
"RefreshInterval": {
"type": "integer",
"description": "The interval to refresh the peer list.",
"format": "int32",
"maximum": 2147483647.0,
"minimum": 0.0
},
"PeerLifetime": {
"type": "integer",
"description": "The lifetime of a peer.",
"format": "int32",
"maximum": 2147483647.0,
"minimum": 0.0
},
"PingTimeout": {
"type": "integer",
"description": "The timeout for a ping.",
"format": "int32",
"maximum": 2147483647.0,
"minimum": 0.0
}
}
},
Expand Down Expand Up @@ -1231,6 +1174,9 @@
"type": "object",
"additionalProperties": false,
"properties": {
"IsEnabled": {
"type": "boolean"
},
"PrivateKey": {
"type": "string",
"description": "The private key of the node.",
Expand All @@ -1252,6 +1198,10 @@
"type": "object",
"additionalProperties": false,
"properties": {
"IsEnabled": {
"type": "boolean",
"default": true
},
"EndPoint": {
"type": "string",
"pattern": "^(?:(?:[a-zA-Z0-9\\-\\.]+)|(?:\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})):\\d{1,5}$"
Expand All @@ -1275,13 +1225,9 @@
"description": "Options for the genesis block.",
"$ref": "#/definitions/Genesis"
},
"BlocksyncSeed": {
"description": "Type 'SeedOptions' does not have a description.",
"$ref": "#/definitions/BlocksyncSeed"
},
"ConsensusSeed": {
"description": "Type 'SeedOptions' does not have a description.",
"$ref": "#/definitions/ConsensusSeed"
"Solo": {
"description": "Type 'SoloOptions' does not have a description.",
"$ref": "#/definitions/Solo"
},
"Store": {
"description": "Type 'StoreOptions' does not have a description.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@
"EndpointDefaults": {
"Protocols": "Http1AndHttp2"
}
},
"Swarm": {
"IsEnabled": true
},
"Validator": {
"IsEnabled": true
}
}
54 changes: 51 additions & 3 deletions sdk/node/Libplanet.Node.Extensions/LibplanetServicesExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using Libplanet.Blockchain;
using Libplanet.Node.Extensions.NodeBuilder;
using Libplanet.Node.Options;
using Libplanet.Node.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;

namespace Libplanet.Node.Extensions;

Expand All @@ -13,9 +16,54 @@ public static ILibplanetNodeBuilder AddLibplanetNode(
{
SynchronizationContext.SetSynchronizationContext(SynchronizationContext.Current ?? new());
services.AddSingleton(SynchronizationContext.Current!);
services.Configure<SoloProposeOption>(configuration.GetSection(SoloProposeOption.Position));
services.AddOptionsFromDomain(configuration);
services.AddOptions<GenesisOptions>()
.Bind(configuration.GetSection(GenesisOptions.Position));
services.AddSingleton<IConfigureOptions<GenesisOptions>, GenesisOptionsConfigurator>();

return new LibplanetNodeBuilder(services, configuration);
services.AddOptions<StoreOptions>()
.Bind(configuration.GetSection(StoreOptions.Position));
services.AddSingleton<IConfigureOptions<StoreOptions>, StoreOptionsConfigurator>();

services.AddOptions<SwarmOptions>()
.Bind(configuration.GetSection(SwarmOptions.Position));
services.AddSingleton<IConfigureOptions<SwarmOptions>, SwarmOptionsConfigurator>();
services.AddSingleton<IValidateOptions<SwarmOptions>, SwarmOptionsValidator>();

services.AddOptions<ValidatorOptions>()
.Bind(configuration.GetSection(ValidatorOptions.Position));
services.AddSingleton<IConfigureOptions<ValidatorOptions>, ValidatorOptionsConfigurator>();
services.AddSingleton<IValidateOptions<ValidatorOptions>, ValidatorOptionsValidator>();

services.AddOptions<SoloOptions>()
.Bind(configuration.GetSection(SoloOptions.Position));
services.AddSingleton<IConfigureOptions<SoloOptions>, SoloOptionsConfigurator>();

services.AddSingleton<PolicyService>();
services.AddSingleton<IBlockChainService, BlockChainService>();
services.AddSingleton<IReadChainService, ReadChainService>();
services.AddSingleton<TransactionService>();

var serviceProvider = services.BuildServiceProvider();
var soloOptions = serviceProvider.GetRequiredService<IOptions<SoloOptions>>();
var swarmOptions = serviceProvider.GetRequiredService<IOptions<SwarmOptions>>();
var validatorOptions = serviceProvider.GetRequiredService<IOptions<ValidatorOptions>>();
var nodeBuilder = new LibplanetNodeBuilder(services);

if (soloOptions.Value.IsEnabled)
{
nodeBuilder.WithSolo();
}

if (swarmOptions.Value.IsEnabled)
{
nodeBuilder.WithSwarm();
}

if (validatorOptions.Value.IsEnabled)
{
nodeBuilder.WithValidator();
}

return nodeBuilder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,9 @@ public interface ILibplanetNodeBuilder
{
IServiceCollection Services { get; }

string[] Scopes { get; }

ILibplanetNodeBuilder WithSolo();

ILibplanetNodeBuilder WithSwarm();

ILibplanetNodeBuilder WithValidator();

ILibplanetNodeBuilder WithSeed();
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
using Libplanet.Node.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace Libplanet.Node.Extensions.NodeBuilder;

public class LibplanetNodeBuilder : ILibplanetNodeBuilder
{
private readonly IConfiguration _configuration;
private readonly List<string> _scopeList = [string.Empty];

internal LibplanetNodeBuilder(IServiceCollection services, IConfiguration configuration)
internal LibplanetNodeBuilder(IServiceCollection services)
{
Services = services;
_configuration = configuration;
Services.AddSingletonsFromDomain();
}

public IServiceCollection Services { get; }
Expand All @@ -23,30 +19,22 @@ internal LibplanetNodeBuilder(IServiceCollection services, IConfiguration config
public ILibplanetNodeBuilder WithSolo()
{
Services.AddHostedService<SoloProposeService>();
_scopeList.Add("Solo");
return this;
}

public ILibplanetNodeBuilder WithSwarm()
{
Services.AddSingletonsFromDomain(scope: "Swarm");
Services.AddOptionsFromDomain(_configuration, scope: "Swarm");
Services.AddSingleton<ISwarmService, SwarmService>();
Services.AddHostedService<SwarmService>();
_scopeList.Add("Swarm");
return this;
}

public ILibplanetNodeBuilder WithValidator()
{
Services.AddSingletonsFromDomain(scope: "Validator");
Services.AddOptionsFromDomain(_configuration, scope: "Validator");
Services.AddSingleton<IValidatorService, ValidatorService>();
_scopeList.Add("Validator");
return this;
}

public ILibplanetNodeBuilder WithSeed()
{
Services.AddSingletonsFromDomain(scope: "Seed");
Services.AddOptionsFromDomain(_configuration, scope: "Seed");
_scopeList.Add("Seed");
return this;
}
}
Loading

0 comments on commit 895c277

Please sign in to comment.