Repository navigation
Host lifecycle
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.
| 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 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.
Nothing listens until everything behind it runs:
- Refuse to start while any schema has migrations pending: "run
NexusTomorrow.Server migratefirst". - Start the write-behind queue.
- Take the first block of character ids, waiting up to
Persistence:FirstIdBlockTimeout, and hand it to the realm owner. - Start the account owner, then the realm owner.
- 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.
- Kestrel stops accepting connections and closes the open ones.
- The realm owner and the account owner stop, each handling what it already has queued.
- The host waits for every queued save to commit, logging the backlog every 5 seconds while it waits.
| 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 |
- 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.
| 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/ |
Start here
How the server works
- Server core design
- Host
- Gateway
- Owners
- Persistence
- Command layer
- Harness
- Map scheduler design
- Timer wheel design
The protocol
Working on it