Skip to content

Host lifecycle

rebaserHEAD edited this page Oct 18, 2026 · 1 revision

reference, committed verified 2026-10-18 bootstrap c3409ba run 2026-10-18

The server process from start to stop: its two verbs, the settings it checks, the order it starts in and the order it stops in. Why it's built this way is on Host, and running it is on Running a server.

The program

Verb Does
NexusTomorrow.Server migrate Applies every schema's migrations and exits: 0 on success, 1 with the error. It never prints the connection string or its password, even in a driver's error
Anything else Runs the server

Settings

Settings come from appsettings.json, then the environment (with __ for :), then the command line. Every settings class is checked when the host starts, before anything touches the database, and a setting that fails stops it with the setting's name, never its value. Among the checks:

Setting Must be
Persistence:ConnectionString Set
Gateway:UnknownAccountSecret At least 32 bytes, in base64
Gateway:WorldPublicAddress An IPv4 address
The three client ports Different from each other
Realm:Id At most 16,383, because the character list carries it in 14 bits
Realm:Name Set

Each system's settings are on its own page: Gateway, Owners, Persistence, Command layer.

Start-up

Nothing listens until everything behind it runs:

  1. Refuse to start while any schema has migrations pending: "run NexusTomorrow.Server migrate first".
  2. Start the write-behind queue.
  3. Take the first block of character ids, waiting up to Persistence:FirstIdBlockTimeout, and hand it to the realm owner.
  4. Start the account owner, then the realm owner.
  5. Open the three listeners, each on loopback unless it's configured otherwise.

If any of steps 3 to 5 fails, the owners already started are stopped, the queue gives up its start-up work, and the start fails with the cause.

Shutdown

  1. Kestrel stops accepting connections and closes the open ones.
  2. The realm owner and the account owner stop, each handling what it already has queued.
  3. The host waits for every queued save to commit, logging the backlog every 5 seconds while it waits.

Beside it

Service Does
The watchdog Checks the owners once a second on the host's clock (Owners base)
The console Reads commands from standard input when Cli:Enabled is on and input isn't redirected (Command layer dispatcher)
Time One injected clock, which the harness replaces with a fake one

Known edges

  • Shutdown waits for every save with no time limit, so a database that's gone for good keeps the process from exiting. Whether to bound it is an open question.
  • Stopping doesn't wait for a console line that never comes.

Where the code lives

Piece Path
The program and the migrate verb Source/NexusTomorrow.Server/Program.cs, Source/NexusTomorrow.Server/ServerHost.cs
Start-up and shutdown Source/NexusTomorrow.Server/CoreLifetime.cs
Settings checks Source/NexusTomorrow.Server/OptionsValidation.cs
The console and the watchdog service Source/NexusTomorrow.Server/ConsoleFrontEnd.cs, Source/NexusTomorrow.Server/OwnerWatchdogService.cs
Default settings Source/NexusTomorrow.Server/appsettings.json
Tests Tests/NexusTomorrow.Server.Tests/

Clone this wiki locally