LocalControlPlane
The control plane's state machine: registrations, heartbeats, leases with epochs and settings, kept in plain lists in this process.
Nebula · Packages/com.1by3.nebula/Runtime/ControlPlane/LocalControlPlane.cspublic sealed partial class LocalControlPlane : IControlPlaneThe control plane's state machine: registrations, heartbeats, leases with epochs and settings, kept in plain lists in this process. Changes are applied synchronously and Changed fires on the next Tick. On its own it serves single-process runs and tests; ControlPlaneHost wraps it on the orchestrator, where it is the source of truth every RemoteControlPlane mirrors.
Properties
IsConnected
public bool IsConnected { get; }Now
public DateTime Now { get; }DocumentId
public string DocumentId { get; } = NewDocumentId();Identity of this control-plane document, preserved on import and replaced on reset.
Workers
public IReadOnlyList<WorkerInfo> Workers { get; }Leases
public IReadOnlyList<LeaseInfo> Leases { get; }Gateways
public IReadOnlyList<GatewayInfo> Gateways { get; }Settings
public IReadOnlyDictionary<string, string> Settings { get; }Version
public long Version { get; }Bumped by every change, so a mirror can tell whether it is behind.
Scopes
public IReadOnlyList<ScopeInfo> Scopes { get; }Events
Changed
public event Action Changed;Methods
Connect
public void Connect();Tick
public void Tick();Dispose
public void Dispose();ToJson
public string ToJson();The whole state as one document (see ControlPlaneJson).
Import
public void Import(ControlPlaneJson.Snapshot snapshot);Replace the whole state with snapshot (a stored document coming back at startup).
RegisterWorker
public void RegisterWorker(string workerId, uint workerIndex, string address, ushort port);HeartbeatWorker
public void HeartbeatWorker(string workerId, string status, in WorkerStats stats);UnregisterWorker
public void UnregisterWorker(string workerId);RegisterGateway
public void RegisterGateway(string gatewayId, string address, ushort port, uint incarnation = 0);HeartbeatGateway
public void HeartbeatGateway(string gatewayId, in GatewayStats stats);UnregisterGateway
public void UnregisterGateway(string gatewayId);SetGatewayDraining
public void SetGatewayDraining(string gatewayId, bool draining);HeartbeatOrchestrator
public void HeartbeatOrchestrator(string orchestratorId, uint desiredWorkers);SetSetting
public void SetSetting(string key, string value);EnsureContainer
public void EnsureContainer(string containerId, ContainerAuthority authority = ContainerAuthority.Auto, bool ownPhysicsFrame = false, FrameInterestMode frameInterest = FrameInterestMode.WithCarrier, float frameApproachMargin = 0f);EnsureRuntimeContainer
public void EnsureRuntimeContainer(string containerId, ContainerPlacement placement, string workerId, InstanceContainerInfo instance = null);TouchContainer
public void TouchContainer(string containerId);AssignContainer
public void AssignContainer(string containerId, string workerId);PinContainer
public void PinContainer(string containerId, string workerId);SetContainerHint
public void SetContainerHint(string containerId, in ContainerHint hint);SetContainerCapacity
public void SetContainerCapacity(string containerId, float saturation, CostComponent dominant, bool atCapacity, SaturationCause cause = SaturationCause.None);SetLeaseState
public void SetLeaseState(string containerId, string state);ReleaseContainer
public void ReleaseContainer(string containerId);RemoveContainer
public void RemoveContainer(string containerId);ResetControlPlane
public void ResetControlPlane();ActivateScope
public void ActivateScope(ScopeActivationRequest request);Make the scope named by request exist, or leave the one that already exists alone. Called on the orchestrator's main thread, which serialises it against every other control-plane write, so the check and the create are one step; the durable claim (IScopeStore) makes the same hold across orchestrator runs.
SetScopeState
public void SetScopeState(string scopeKey, string state);Move a scope to another lifecycle state (ScopeState). The orchestrator's sweep is the only caller in Nebula: it is the single writer of the machine, which is what keeps the ordering guarantees (docs/scope-lifecycle.md). The acknowledgements of the previous step are dropped with the change.
AckScopePart
public void AckScopePart(string scopeKey, string containerId, string phase, int count, string workerId);A worker reporting that it finished the step the scope is in for one of its containers (ScopePhase). Recorded on the row, so the orchestrator's next sweep sees it and every other role can watch the progress. The container must be one of the scope's live parts (ScopeLifecycle.CollectParts): named by the row, or leased under the scope's key. An ack for any other container, or in a phase that does not match the scope's state, is dropped: it belongs to a step that has already ended.
RemoveScope
public void RemoveScope(string scopeKey);Drop a scope row, its claim and the lease rows of its containers. The explicit way out, whatever state the row is in.