Skip to content

Feature/hosted services#176

Open
mdickson wants to merge 16 commits into
developfrom
feature/hosted-services
Open

Feature/hosted services#176
mdickson wants to merge 16 commits into
developfrom
feature/hosted-services

Conversation

@mdickson

Copy link
Copy Markdown
Collaborator

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.

Mike Dickson added 16 commits June 23, 2026 13:16
…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).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant