using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using ZB.MOM.WW.CBDDC.Core; using ZB.MOM.WW.CBDDC.Core.Storage; using ZB.MOM.WW.CBDDC.Core.Cache; using ZB.MOM.WW.CBDDC.Core.Sync; using ZB.MOM.WW.CBDDC.Core.Diagnostics; using ZB.MOM.WW.CBDDC.Core.Resilience; using ZB.MOM.WW.CBDDC.Network; using ZB.MOM.WW.CBDDC.Network.Security; using ZB.MOM.WW.CBDDC.Persistence.BLite; using ZB.MOM.WW.CBDDC.Sample.Console; using Microsoft.Extensions.Hosting; using Serilog; using ZB.MOM.WW.CBDDC.Core.Network; namespace ZB.MOM.WW.CBDDC.Sample.Console; // Local User/Address classes removed in favor of Shared project class Program { static async Task Main(string[] args) { var builder = Host.CreateApplicationBuilder(args); // Configuration builder.Configuration.SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); // Logging builder.Logging.ClearProviders(); builder.Services.AddSerilog((_, loggerConfiguration) => loggerConfiguration .MinimumLevel.Information() .Enrich.FromLogContext() .Enrich.WithProperty("Application", "CBDDC.Sample.Console") .WriteTo.Console()); var randomPort = new Random().Next(1000, 9999); // Node ID string nodeId = args.Length > 0 ? args[0] : ("node-" + randomPort); int tcpPort = args.Length > 1 ? int.Parse(args[1]) : randomPort; // Conflict Resolution Strategy (can be switched at runtime via service replacement) var useRecursiveMerge = args.Contains("--merge"); if (useRecursiveMerge) { builder.Services.AddSingleton(); } IPeerNodeConfigurationProvider peerNodeConfigurationProvider = new StaticPeerNodeConfigurationProvider( new PeerNodeConfiguration { NodeId = nodeId, TcpPort = tcpPort, AuthToken = "Test-Cluster-Key", //KnownPeers = builder.Configuration.GetSection("CBDDC:KnownPeers").Get>() ?? new() }); builder.Services.AddSingleton(peerNodeConfigurationProvider); // Database path var dataPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "data"); Directory.CreateDirectory(dataPath); var databasePath = Path.Combine(dataPath, $"{nodeId}.blite"); // Register CBDDC Services using Fluent Extensions with BLite, SampleDbContext, and SampleDocumentStore builder.Services.AddCBDDCCore() .AddCBDDCBLite(sp => new SampleDbContext(databasePath)) .AddCBDDCNetwork(); // useHostedService = true by default builder.Services.AddHostedService(); // Runs the Input Loop var host = builder.Build(); System.Console.WriteLine($"? Node {nodeId} initialized on port {tcpPort}"); System.Console.WriteLine($"? Database: {databasePath}"); System.Console.WriteLine(); await host.RunAsync(); } private class StaticPeerNodeConfigurationProvider : IPeerNodeConfigurationProvider { /// /// Gets or sets the current peer node configuration. /// public PeerNodeConfiguration Configuration { get; set; } /// /// Initializes a new instance of the class. /// /// The initial peer node configuration. public StaticPeerNodeConfigurationProvider(PeerNodeConfiguration configuration) { Configuration = configuration; } /// /// Occurs when the peer node configuration changes. /// public event PeerNodeConfigurationChangedEventHandler? ConfigurationChanged; /// /// Gets the current peer node configuration. /// /// A task that returns the current configuration. public Task GetConfiguration() { return Task.FromResult(Configuration); } /// /// Raises the configuration changed event. /// /// The new configuration value. protected virtual void OnConfigurationChanged(PeerNodeConfiguration newConfig) { ConfigurationChanged?.Invoke(this, newConfig); } } }