Feature/hosted services#176
Open
mdickson wants to merge 16 commits into
Open
Conversation
added 16 commits
June 23, 2026 13:16
…oney, Grid and Region servers.
…ice C2 A3 - Legacy Nini configuration adapter (OpenSim.Server.Base.Hosting) - ILegacyConfigSourceAccessor / LegacyIniConfigSourceAccessor - Builds Nini IConfigSource from ServerStartupOptions with same master->files->directory precedence as the hosted pipeline - Registered in DI and consumed by MoneyServer IServerBase.Config B4 - Startup failure coordination (OpenSim.Server.Base.Hosting) - IStartupFailureCoordinator / StartupFailureCoordinator - ThrowFatal() replaces Environment.Exit in startup hot paths - RequestStop() delegates to IHostApplicationLifetime.StopApplication C1/C2 - MoneyService constructor and runtime seam refactor - IMoneyServerRuntime / MoneyServerRuntime owns initialization, maintenance timer, and shutdown infrastructure - MoneyService constructor is now dependency-capture only - EnsureInitialized block replaced by runtime.Initialize() - Work() delegates maintenance timer to runtime.StartMaintenance() - StopAsync delegates to runtime.Stop() - IMoneyDBService gains Initialise() so runtime depends on abstraction - IStartupFailureCoordinator replaces Environment.Exit in touched paths Tests - LegacyIniConfigSourceAccessorTests: precedence, override, sorted dir, null guard - StartupFailureCoordinatorTests: throws on fatal, preserves inner exception, calls host StopApplication on RequestStop
C3 - MoneyConsoleRunnerService (BackgroundService) - Moves blocking console prompt loop out of MoneyService.StartAsync into a dedicated BackgroundService so the host finishes its start sequence before user input is accepted - Waits for IHostApplicationLifetime.ApplicationStarted before entering the prompt loop - Runs the blocking Prompt() call on a thread-pool thread via Task.Run so the host's async machinery is never blocked - Respects CancellationToken; exits cleanly on host shutdown C3 - MoneyService.StartAsync now returns promptly - Removed Work() method (loop moved to MoneyConsoleRunnerService) - StartAsync sequence: Initialize -> StartMaintenance -> Startup -> return C4 - Dead code removal in MoneyService - Removed vestigial Shutdown() protected method (duplicate of StopAsync) - Removed unreferenced LogDiagnostics() method and its unused imports (System.Timers, System.Text) Program.cs - Registered MoneyConsoleRunnerService as hosted service Tests - MoneyConsoleRunnerServiceTests (xUnit) - DoesNotPrompt before ApplicationStarted fires - Prompts after ApplicationStarted using SemaphoreSlim synchronisation - ExitsCleanly when cancelled before started - ICommandConsole fake correctly dispatches Prompt() through interface
C5 - host lifetime integration coverage (xUnit) - Added MoneyServiceHostLifecycleTests with real HostBuilder wiring - Verifies clean start/stop lifecycle: Initialize + StartMaintenance on start and Stop on host shutdown - Verifies startup failure propagation when runtime Initialize throws - Verifies startup failure coordinator path when startup registration fails Test project updates - Added Microsoft.Extensions.Hosting package reference to OpenSim.Server.Base.Tests for HostBuilder-based integration tests Validation - dotnet build Source/OpenSim.Server.MoneyServer/OpenSim.Server.MoneyServer.csproj --configuration Debug - dotnet test Tests/OpenSim.Server.Base.Tests/OpenSim.Server.Base.Tests.csproj --configuration Debug
- Add ILog4NetBootstrapper and Log4NetBootstrapper in Server.Base.Hosting - Centralize log4net config path resolution with explicit server default fallback - Configure log4net through shared bootstrapper in MoneyServer and GridServer Program startup - Use effective log4net config path consistently in Microsoft logging provider setup - Add xUnit tests for bootstrapper path resolution behavior
A6 shared startup extraction - Added IProcessSetupService + ProcessSetupService with ProcessSetupOptions for process-level startup defaults (culture, HTTP service point settings, DNS timeout, optional threadpool max bounds) - Added ProcessSetupHostedService to apply process defaults under host lifecycle - Added IPidFileManager + PidFileManager to own PID create/remove behavior - Added PidFileHostedService to create PID file at startup and remove it at shutdown via host lifecycle Program integration - Registered process setup and PID services in MoneyServer and GridServer host startup - Added hosted service registrations so these concerns run inside host-managed lifecycle Tests (xUnit) - ProcessSetupServiceTests - PidFileManagerTests - PidFileHostedServiceTests Validation - dotnet build Source/OpenSim.Server.MoneyServer/OpenSim.Server.MoneyServer.csproj --configuration Debug - dotnet build Source/OpenSim.Server.GridServer/OpenSim.Server.GridServer.csproj --configuration Debug - dotnet test Tests/OpenSim.Server.Base.Tests/OpenSim.Server.Base.Tests.csproj --configuration Debug
B2 main server accessor - Added IMainServerAccessor + MainServerAccessor to centralize access to MainServer.Instance (DefaultServer, GetHttpServer, Stop) B3 runtime monitoring controller - Added IRuntimeMonitoringController + RuntimeMonitoringController to isolate Watchdog, MemoryWatchdog and WorkManager lifecycle calls MoneyServer adoption - MoneyServerRuntime now stops via injected IMainServerAccessor and IRuntimeMonitoringController instead of static MainServer/Watchdog/WorkManager calls - Registered new wrappers in MoneyServer host composition GridServer adoption - GridService now resolves connector HTTP servers and performs shutdown lifecycle via injected wrappers - Registered new wrappers in GridServer host composition Tests (xUnit) - Added MainServerAccessorTests and RuntimeMonitoringControllerTests Validation - dotnet build Source/OpenSim.Server.MoneyServer/OpenSim.Server.MoneyServer.csproj --configuration Debug - dotnet build Source/OpenSim.Server.GridServer/OpenSim.Server.GridServer.csproj --configuration Debug - dotnet test Tests/OpenSim.Server.Base.Tests/OpenSim.Server.Base.Tests.csproj --configuration Debug
Move legacy HTTP boot, connector loading and plugin loader setup out of the GridService constructor into a BuildServer() method invoked during StartAsync. Remove m_Server.Run(), m_Server.Shutdown() and Environment.Exit(res) from the constructor so the generic host owns process lifetime. Add xUnit tests proving construction touches none of its injected dependencies.
Replace the legacy ServicesServerBase.Run() blocking prompt loop with a GridConsoleRunnerService BackgroundService that waits for ApplicationStarted, then runs Console.Prompt() on a thread-pool thread and exits cleanly on cancellation. GridService.StartAsync now returns promptly after BuildServer() and Startup(); the dead Work() loop is removed. Register the runner in Program.cs. Add xUnit tests for the runner lifecycle.
- D3: extract IServiceConnectorLoader/GridServiceConnectorLoader for connector activation - D2: add IGridServerRuntime/GridServerRuntime owning HTTP listener bootstrap and plugin loader - D5: slim GridService to host-lifetime orchestration; route fatal startup through IStartupFailureCoordinator instead of Environment.Exit - D6: add GridServiceHostLifecycleTests; update GridServiceConstructionTests for new constructor
- E1: replace Application.Main() with Program.cs generic-host bootstrap - E2: add IRegionRuntime/RegionRuntime adapter + RegionService hosted service - E3: foreground/background mode is now a host config concern, not inheritance - E4: add RegionConsoleRunnerService for interactive prompt loop (foreground only) - E5: remove Environment.Exit and ManualResetEvent lifetime ownership from migrated paths - route fatal startup errors through IStartupFailureCoordinator - apply process defaults via shared IProcessSetupService - keep Application static crash handler + iniFilePath (used by ConfigurationLoader) - add RegionService host-lifetime tests (58 tests pass)
Move runtime concerns out of the RegionServer startup inheritance chain into dedicated, testable composed services. F1 - Diagnostics + monitoring lifecycle: - Extract periodic diagnostics timer into IRegionDiagnosticsService/ RegionDiagnosticsService. - Remove timer fields, LogDiagnostics, and Watchdog/WorkManager teardown from BaseOpenSimServer; lift watchdog + WorkManager + diagnostics lifecycle to RegionRuntime via IRuntimeMonitoringController. Neutralize legacy Environment.Exit(0) via SuppressExit. F2 - HTTP listeners + status handlers: - Extract listener creation into IRegionHttpServerFactory/RegionHttpServerFactory; RegionApplicationBase delegates. - Extract status/stream-handler registration into IRegionStatusHandlerRegistrar/ RegionStatusHandlerRegistrar; OpenSim delegates. Make UXSimStatusHandler public. F3 - Plugins + scripts: - Extract plugin load/post-initialise/dispose into IRegionPluginService/ RegionPluginService; OpenSimBase delegates. - Extract startup/shutdown/timed command scripts into IRegionStartupScriptService/ RegionStartupScriptService; OpenSim delegates. Add unit tests for the diagnostics, plugin, and startup-script services. Full solution builds with 0 errors; 75 tests pass.
…g cleanup F4: Extract certificate provisioning and region-ready watchdog wiring out of OpenSimBase.Initialize into composed services (IRegionCertificateProvisioner, IRegionReadyStatusMonitor) with testable seams; behavior preserved verbatim. F5: Add RegionServer host-lifetime integration tests for interactive and background modes plus RegionConsoleRunnerService tests; serialize MainConsole static mutation via a dedicated xUnit collection. X1: Audit Environment.Exit usage on hosted paths (Docs/HostedServiceEnvironmentExitAudit.md). X2: Document hosted startup/shutdown sequence and compatibility shims (Docs/HostedServiceStartupShutdownSequence.md). X3: Add migration regression test checklist (Docs/HostedServiceMigrationRegressionChecklist.md). Full solution builds with 0 errors; 89 tests pass (was 75).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Move develop away from the old Static Class initialization startup logic and to a WorkerService dotnet core pattern that also allows for future DI throughout the codebase. Planning docs in Docs.