Nebula
Control plane

ScopeLifecycle

The scope lifecycle's pure parts: how idle age and occupancy are aggregated from a scope's parts, when a scope should retire, and whether a client may be admitted to it.

generated from the sources
public static class ScopeLifecycle

The scope lifecycle's pure parts: how idle age and occupancy are aggregated from a scope's parts, when a scope should retire, and whether a client may be admitted to it. The orchestrator drives the state machine with these; they hold no state of their own, so a test can drive the whole sequence without a mesh. Design of record: docs/scope-lifecycle.md.

Fields

StepTimeoutSeconds

public const float StepTimeoutSeconds = 30f;

How long the orchestrator waits for every part to acknowledge a retire or a restore before it gives up and finishes the step anyway. A worker that died mid-step must not leave a scope stuck in ScopeState.Retiring (nothing could ever enter it again) or in ScopeState.Restoring (nobody could ever join it).

ShouldRetire

public static ScopeRetirePolicy ShouldRetire = RetireWhenIdle;

Consulted for every ScopeState.Active scope on the orchestrator's idle sweep. Replace it to keep a scope hot for reasons Nebula cannot see — a raid whose party is still in the queue, a housing instance its owner is about to re-enter, a scope a live event is scheduled in. The default is RetireWhenIdle. It is consulted, never obeyed blindly: a scope that is not idle is never offered to it.

Methods

RetireWhenIdle

public static bool RetireWhenIdle(in ScopeRetireContext context);

The default policy: retire once the scope has held no client-owned entity and no authoritative entity at all for ScopeRetireContext.RetireAfterSeconds. With ScopeRetireContext.RetireWithEntities, only client-owned entities keep it: a scope that holds saved objects and nobody playing retires once it is idle. Pure.

CollectParts

public static void CollectParts(IControlPlane cp, ScopeInfo scope, List<string> into);

The scope's live parts, into into (cleared first): the containers its row names, then every other lease row whose InstanceContainerInfo.ScopeKey is the scope's key. For a ScopeKind.Parts scope the two are the same set. A ScopeKind.Grid scope's row names only its anchor chunk; the rest are the chunks the allocator leased on demand around the scope's pawns. Idle age, occupancy and the retire sequence are all judged over this set, so a player standing three chunks from the anchor keeps the scope alive (docs/scope-lifecycle.md D4).

IndexParts

public static void IndexParts(IControlPlane cp, Dictionary<string, List<string>> into);

CollectParts for every scope row at once, keyed by scope key, in one pass over the lease rows. For a caller that visits every scope: the orchestrator's sweep and a worker's lifecycle pass. Lists already in into are cleared and reused.

IdleSeconds

public static double IdleSeconds(IControlPlane cp, ScopeInfo scope);
public static double IdleSeconds(IControlPlane cp, IReadOnlyList<string> parts);

Seconds since anything last wanted any live part of the scope (CollectParts); see the other overload.

Occupancy

public static void Occupancy(ScopeInfo scope, IReadOnlyDictionary<string, ContainerLoad> occupancy, out int entities, out int players);
public static void Occupancy(IReadOnlyList<string> parts, IReadOnlyDictionary<string, ContainerLoad> occupancy, out int entities, out int players);

What the workers last reported inside the containers the scope's row names, summed over them. A grid scope's row names only its anchor: pass its live parts (CollectParts) to the other overload.

Admits

public static bool Admits(IControlPlane cp, string scopeKey, out JoinHoldReason reason);

Whether a client naming scopeKey may be placed now, and why not when it may not. A key with no row at all is JoinHoldReason.ScopeNotReady: the gateway never activates a scope, so the client waits for whoever sent it there (docs/scope-activation.md §5). The public world (an empty key) is always admitted here; whether there is a container to spawn into is the caller's next question.

NextState

public static string NextState(ScopeInfo scope, double elapsedSeconds, out bool timedOut);
public static string NextState(ScopeInfo scope, IReadOnlyList<string> parts, double elapsedSeconds, out bool timedOut);

The next state of a scope in a step that waits on its parts, or null when it should stay where it is. Pure, so the ordering ("every part, or the deadline") is one testable function rather than a shape of the orchestrator's loop: ScopeState.Retiring ends in ScopeState.Retired and ScopeState.Restoring in ScopeState.Active, once every container has acknowledged the step's phase or elapsedSeconds has passed StepTimeoutSeconds.

On this page