feat(runtime): freeze initial placement inbound admission

This commit is contained in:
Erik 2026-08-01 21:00:03 +02:00
parent 9d601817b8
commit 30012361e1
9 changed files with 2506 additions and 323 deletions

View file

@ -1,3 +1,4 @@
using System.Collections.Immutable;
using AcDream.Core.Items;
using AcDream.Core.Net;
using AcDream.Core.Net.Messages;
@ -11,7 +12,8 @@ public readonly record struct RuntimeEntityRegistrationResult(
RuntimeEntityRecord? Canonical,
bool LogicalRegistrationCreated,
bool ReplacedExistingGeneration,
Exception? PriorGenerationCleanupFailure = null);
Exception? PriorGenerationCleanupFailure = null,
bool DeferredForParent = false);
public readonly record struct RuntimeEntityObjectOwnershipSnapshot(
int ActiveEntityCount,
@ -19,6 +21,7 @@ public readonly record struct RuntimeEntityObjectOwnershipSnapshot(
int ClaimedLocalIdCount,
int AcceptedSnapshotCount,
int UnresolvedParentRelationCount,
int DeferredParentCreateCount,
int StagedParentRelationCount,
int RecoveryParentRelationCount,
int CommittedParentRelationCount,
@ -44,6 +47,7 @@ public readonly record struct RuntimeEntityObjectOwnershipSnapshot(
&& ClaimedLocalIdCount == 0
&& AcceptedSnapshotCount == 0
&& UnresolvedParentRelationCount == 0
&& DeferredParentCreateCount == 0
&& StagedParentRelationCount == 0
&& RecoveryParentRelationCount == 0
&& CommittedParentRelationCount == 0
@ -205,6 +209,7 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
Entities.ClaimedLocalIdCount,
Entities.Snapshots.Count,
parents.UnresolvedRelationCount,
parents.DeferredCreateCount,
parents.StagedRelationCount,
parents.RecoveryRelationCount,
parents.CommittedRelationCount,
@ -272,6 +277,35 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
throw new InvalidOperationException(
"A Runtime entity cannot register while its session lifetime is clearing.");
}
if (beginInitialResidence
&& !HasConsistentCreateIdentityAndParent(incoming))
{
throw new InvalidOperationException(
$"CreateObject 0x{incoming.Guid:X8} has inconsistent instance or parent projections.");
}
if (beginInitialResidence)
incoming = RuntimeInitialCreateAdmissionFreezer.Freeze(incoming);
uint parentGuid = incoming.ParentGuid
?? incoming.Physics?.Parent?.Guid
?? 0u;
if (beginInitialResidence
&& parentGuid != 0u
&& !Entities.TryGetActive(parentGuid, out _))
{
// SmartBox::HandleCreateObject resolves a nonzero parent before
// object lookup or timestamp admission. Retain the complete raw
// CreateObject so no child gate/canonical/projection state can
// escape before the parent becomes addressable.
Entities.ParentAttachments.EnqueueDeferredCreate(
incoming,
isLocalPlayer);
return new RuntimeEntityRegistrationResult(
SupersededCreateResult(),
Canonical: null,
LogicalRegistrationCreated: false,
ReplacedExistingGeneration: false,
DeferredForParent: true);
}
CreateObjectTimestampDisposition preview =
Entities.PreviewCreateDisposition(incoming);
bool requiresFreshResidenceAdmission = preview is
@ -285,7 +319,44 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
$"CreateObject 0x{incoming.Guid:X8} cannot acquire a structurally valid initial residence lease.");
}
InboundCreateResult result = Entities.AcceptCreate(incoming);
RuntimeEntityRecord? pendingResidenceRecord = null;
RuntimeInitialCreateResidenceLease pendingResidence = default;
bool admitIntoPendingResidence = beginInitialResidence
&& preview is CreateObjectTimestampDisposition.ExistingGeneration
&& Entities.TryGetActive(
incoming.Guid,
out pendingResidenceRecord)
&& InitialCreateResidences.TryGetTransaction(
pendingResidenceRecord,
out pendingResidence);
if (admitIntoPendingResidence
&& !InitialCreateResidences.CanEnqueue(
pendingResidenceRecord!,
pendingResidence))
{
throw new InvalidOperationException(
$"CreateObject 0x{incoming.Guid:X8} cannot append to its pending initial residence FIFO.");
}
if (admitIntoPendingResidence
&& !IsStructurallyValidDeferredCreate(incoming))
{
_ = Entities.TryGetAcceptedTimestamps(
incoming.Guid,
out AcceptedPhysicsTimestamps timestamps);
return new RuntimeEntityRegistrationResult(
new InboundCreateResult(
CreateObjectTimestampDisposition.ExistingGeneration,
pendingResidenceRecord!.Snapshot,
SameGenerationEvents: null,
timestamps),
pendingResidenceRecord,
LogicalRegistrationCreated: false,
ReplacedExistingGeneration: false);
}
InboundCreateResult result = admitIntoPendingResidence
? Entities.AcceptCreateDeferredSameGeneration(incoming)
: Entities.AcceptCreate(incoming);
if (result.Disposition
is CreateObjectTimestampDisposition.StaleGeneration)
{
@ -307,6 +378,33 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
incoming.Guid,
out RuntimeEntityRecord retained))
{
if (admitIntoPendingResidence)
{
if (!ReferenceEquals(retained, pendingResidenceRecord)
|| !AdmitSameGenerationCreate(
retained,
pendingResidence,
incoming,
result,
isLocalPlayer))
{
throw FailInitialResidenceRegistration(
retained,
publishDeleted: true);
}
InboundCreateResult dormant = result with
{
Snapshot = retained.Snapshot,
SameGenerationEvents = null,
};
return new RuntimeEntityRegistrationResult(
dormant,
retained,
LogicalRegistrationCreated: false,
ReplacedExistingGeneration: false);
}
// Existing-generation CreateObject contributes untimestamped
// description fields here. Position/Parent/Pickup/State/etc.
// remain separate freshness-gated events and must not churn a
@ -592,6 +690,33 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
out WorldSession.EntitySpawn accepted)
{
EnsureNotDisposed();
if (TryGetPendingInitialResidence(
update.Guid,
out RuntimeEntityRecord pending,
out RuntimeInitialCreateResidenceLease lease))
{
if (!InitialCreateResidences.CanEnqueue(pending, lease))
{
accepted = pending.Snapshot;
return false;
}
bool acceptedByGate = Entities.TryAcceptDeferredObjDesc(
update,
out _);
accepted = pending.Snapshot;
if (!acceptedByGate)
return false;
EnqueueDormant(
pending,
lease,
RuntimeInitialCreateContinuationKind.ObjDesc,
RuntimeAcceptedPositionSource.Unknown,
new RuntimeInitialCreateTailAction(
RuntimeInitialCreateTailActionKind.ObjDesc,
update.Guid,
ObjDesc: update));
return true;
}
bool applied = Entities.TryApplyObjDesc(update, out accepted);
if (!applied
|| !Entities.TryGetActive(
@ -617,6 +742,33 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
out WorldSession.EntitySpawn accepted)
{
EnsureNotDisposed();
if (TryGetPendingInitialResidence(
update.Guid,
out RuntimeEntityRecord pending,
out RuntimeInitialCreateResidenceLease lease))
{
if (!InitialCreateResidences.CanEnqueue(pending, lease))
{
accepted = pending.Snapshot;
return false;
}
bool acceptedByGate = Entities.TryAcceptDeferredPickup(
update,
out _);
accepted = pending.Snapshot;
if (!acceptedByGate)
return false;
EnqueueDormant(
pending,
lease,
RuntimeInitialCreateContinuationKind.Pickup,
RuntimeAcceptedPositionSource.Unknown,
new RuntimeInitialCreateTailAction(
RuntimeInitialCreateTailActionKind.Pickup,
update.Guid,
Pickup: update));
return true;
}
bool applied = Entities.TryApplyPickup(update, out accepted);
if (!applied
|| !Entities.TryGetActive(
@ -655,6 +807,14 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
out WorldSession.EntitySpawn accepted)
{
EnsureNotDisposed();
if (TryGetPendingInitialResidence(
update.ChildGuid,
out _,
out _))
{
throw new InvalidOperationException(
"A CreateObject parent relation must be admitted inside its atomic same-generation Create envelope.");
}
bool applied = Entities.TryApplyCreateParent(update, out accepted);
return CommitPositionChannelUpdate(
applied,
@ -669,6 +829,44 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
out WorldSession.EntitySpawn accepted)
{
EnsureNotDisposed();
if (TryGetPendingInitialResidence(
update.ChildGuid,
out RuntimeEntityRecord pending,
out RuntimeInitialCreateResidenceLease lease))
{
if (!InitialCreateResidences.CanEnqueue(pending, lease))
{
accepted = pending.Snapshot;
return false;
}
if (!Entities.TryGetActive(
update.ParentGuid,
out RuntimeEntityRecord parent)
|| parent.Incarnation != update.ParentInstanceSequence)
{
Entities.ParentAttachments.Enqueue(update);
accepted = pending.Snapshot;
return false;
}
bool acceptedByGate = Entities.TryAcceptDeferredParent(
update,
out AcceptedPhysicsTimestamps timestamps);
accepted = pending.Snapshot;
if (!acceptedByGate)
return false;
EnqueueDormant(
pending,
lease,
RuntimeInitialCreateContinuationKind.Parent,
RuntimeAcceptedPositionSource.Unknown,
new RuntimeInitialCreateTailAction(
RuntimeInitialCreateTailActionKind.Parent,
update.ChildGuid,
Parent: update,
AcceptedTimestamps: timestamps));
return true;
}
bool applied = Entities.TryApplyParent(update, out accepted);
return CommitPositionChannelUpdate(
applied,
@ -750,6 +948,39 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
out AcceptedPhysicsTimestamps timestamps)
{
EnsureNotDisposed();
if (TryGetPendingInitialResidence(
update.Guid,
out RuntimeEntityRecord pending,
out RuntimeInitialCreateResidenceLease lease))
{
if (!InitialCreateResidences.CanEnqueue(pending, lease))
{
accepted = pending.Snapshot;
timestamps = default;
return false;
}
bool payloadApplied = Entities.TryAcceptDeferredMotion(
update,
out timestamps,
out bool timestampMutation);
accepted = pending.Snapshot;
if (!payloadApplied && !timestampMutation)
return false;
EnqueueDormant(
pending,
lease,
RuntimeInitialCreateContinuationKind.Movement,
RuntimeAcceptedPositionSource.Unknown,
new RuntimeInitialCreateTailAction(
RuntimeInitialCreateTailActionKind.Movement,
update.Guid,
Movement: update,
AcceptedTimestamps: timestamps,
AppliesMovementPayload: payloadApplied,
RetainMovementPayload: retainPayload,
HasTimestampMutation: timestampMutation));
return payloadApplied;
}
bool applied = Entities.TryApplyMotion(
update,
retainPayload,
@ -790,6 +1021,35 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
out WorldSession.EntitySpawn accepted)
{
EnsureNotDisposed();
if (TryGetPendingInitialResidence(
update.Guid,
out RuntimeEntityRecord pending,
out RuntimeInitialCreateResidenceLease lease))
{
if (!IsFinite(update.Velocity)
|| !IsFinite(update.Omega)
|| !InitialCreateResidences.CanEnqueue(pending, lease))
{
accepted = pending.Snapshot;
return false;
}
bool acceptedByGate = Entities.TryAcceptDeferredVector(
update,
out _);
accepted = pending.Snapshot;
if (!acceptedByGate)
return false;
EnqueueDormant(
pending,
lease,
RuntimeInitialCreateContinuationKind.Vector,
RuntimeAcceptedPositionSource.Unknown,
new RuntimeInitialCreateTailAction(
RuntimeInitialCreateTailActionKind.Vector,
update.Guid,
Vector: update));
return true;
}
bool applied = Entities.TryApplyVector(update, out accepted);
if (!applied
|| !Entities.TryGetActive(
@ -817,6 +1077,35 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
out RetailPhysicsStateTransition transition)
{
EnsureNotDisposed();
if (TryGetPendingInitialResidence(
update.Guid,
out RuntimeEntityRecord pending,
out RuntimeInitialCreateResidenceLease lease))
{
if (!InitialCreateResidences.CanEnqueue(pending, lease))
{
accepted = pending.Snapshot;
transition = default;
return false;
}
bool acceptedByGate = Entities.TryAcceptDeferredState(
update,
out _);
accepted = pending.Snapshot;
transition = default;
if (!acceptedByGate)
return false;
EnqueueDormant(
pending,
lease,
RuntimeInitialCreateContinuationKind.State,
RuntimeAcceptedPositionSource.Unknown,
new RuntimeInitialCreateTailAction(
RuntimeInitialCreateTailActionKind.State,
update.Guid,
State: update));
return true;
}
bool applied = Entities.TryApplyState(update, out accepted);
transition = default;
if (!applied
@ -883,24 +1172,58 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
out AcceptedPhysicsTimestamps timestamps)
{
EnsureNotDisposed();
RuntimeInitialCreateResidenceLease priorInitialResidence = default;
bool hadPendingInitialResidence =
Entities.TryGetActive(
if (TryGetPendingInitialResidence(
update.Guid,
out RuntimeEntityRecord pendingCanonical)
&& InitialCreateResidences.TryGetTransaction(
pendingCanonical,
out priorInitialResidence);
if (hadPendingInitialResidence
&& !InitialCreateResidences.CanEnqueueAcceptedPosition(
pendingCanonical,
priorInitialResidence,
update))
out RuntimeEntityRecord pendingCanonical,
out RuntimeInitialCreateResidenceLease pendingLease))
{
disposition = PositionTimestampDisposition.Rejected;
accepted = default;
timestamps = default;
return false;
if (!RuntimeAuthoritativePositionRouteClassifier
.IsValidCreateWirePosition(update.Position)
|| update.Velocity is { } velocity
&& !IsFinite(velocity)
|| !InitialCreateResidences.CanEnqueue(
pendingCanonical,
pendingLease))
{
disposition = PositionTimestampDisposition.Rejected;
accepted = default;
timestamps = default;
return false;
}
bool deferredKnown = Entities.TryAcceptDeferredPosition(
update,
isLocalPlayer,
out disposition,
out timestamps,
out bool timestampMutation);
accepted = pendingCanonical.Snapshot;
if (!deferredKnown)
return false;
if (disposition is PositionTimestampDisposition.Rejected
&& !timestampMutation)
{
return true;
}
EnqueueDormant(
pendingCanonical,
pendingLease,
RuntimeInitialCreateContinuationKind.Position,
RuntimeAcceptedPositionSource.PositionEvent,
new RuntimeInitialCreateTailAction(
RuntimeInitialCreateTailActionKind.Position,
update.Guid,
Position: update,
PositionSource:
RuntimeAcceptedPositionSource.PositionEvent,
PositionDisposition: disposition,
PreviousTeleportSequence:
timestamps.PreviousTeleport,
AcceptedTimestamps: timestamps,
HasTimestampMutation: timestampMutation));
return true;
}
bool hadCanonical = Entities.TryGetActive(
update.Guid,
@ -938,43 +1261,6 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
|| projectionRequiresTeleportHook,
};
}
// Initial CreateObject residence is one immutable transaction. A
// Position packet accepted before its 0x11 placement completes is
// retained in the transaction's ordered continuation batch; it must
// not replace the initial mover operation, mutate the Runtime record
// used to prepare that operation, or escape through a host callback.
if (hadPendingInitialResidence)
{
if (!acceptedPosition)
return true;
if (!ReferenceEquals(canonical, pendingCanonical))
throw FailInitialResidenceRegistration(
canonical,
publishDeleted: true);
RuntimeInitialCreateResidenceLease retained =
InitialCreateResidences.EnqueueAcceptedPosition(
canonical,
priorInitialResidence,
update,
accepted,
disposition,
timestamps,
isLocalPlayer,
forcePositionRotation,
currentLocalVelocity,
projectionRequiresTeleportHook);
if (!retained.IsValid)
{
throw FailInitialResidenceRegistration(
canonical,
publishDeleted: true);
}
return true;
}
RuntimePlacementCancellationReceipt cancellation = default;
if (acceptedPosition)
{
@ -1118,6 +1404,15 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
out RuntimeEntityDeleteAcceptance acceptance)
{
EnsureNotDisposed();
if (!isLocalPlayer)
{
// A child whose complete raw CreateObject is waiting on a missing
// parent has no timestamp gate yet. Cancel its exact/older raw
// generation before the normal known-object delete gate returns.
Entities.ParentAttachments.CancelDeferredChildGeneration(
delete.Guid,
delete.InstanceSequence);
}
if (!Entities.TryDelete(delete, isLocalPlayer))
{
acceptance = null!;
@ -1414,6 +1709,288 @@ public sealed class RuntimeEntityObjectLifetime : IDisposable
Entities.IsCurrent(canonical)
&& matchesCommittedMutation();
private bool TryGetPendingInitialResidence(
uint guid,
out RuntimeEntityRecord canonical,
out RuntimeInitialCreateResidenceLease lease)
{
if (Entities.TryGetActive(guid, out canonical)
&& InitialCreateResidences.TryGetTransaction(
canonical,
out lease))
{
return true;
}
canonical = null!;
lease = default;
return false;
}
private void EnqueueDormant(
RuntimeEntityRecord canonical,
in RuntimeInitialCreateResidenceLease prior,
RuntimeInitialCreateContinuationKind kind,
RuntimeAcceptedPositionSource positionSource,
in RuntimeInitialCreateTailAction action)
{
RuntimeInitialCreateResidenceLease retained = InitialCreateResidences
.EnqueueAccepted(
canonical,
prior,
kind,
positionSource,
ImmutableArray.Create(action));
if (!retained.IsValid)
{
throw new InvalidOperationException(
$"Accepted {kind} for 0x{canonical.ServerGuid:X8}/{canonical.Incarnation} could not be retained by its initial-placement FIFO.");
}
}
private static bool IsFinite(System.Numerics.Vector3 value) =>
float.IsFinite(value.X)
&& float.IsFinite(value.Y)
&& float.IsFinite(value.Z);
private static bool HasConsistentCreateIdentityAndParent(
in WorldSession.EntitySpawn incoming)
{
if (incoming.Guid == 0u)
return false;
bool hasTopParentGuid = incoming.ParentGuid is not null;
bool hasTopParentLocation = incoming.ParentLocation is not null;
if (hasTopParentGuid != hasTopParentLocation)
return false;
if (incoming.Physics is not { } physics)
{
// These flattened values are parser projections of PhysicsDesc.
// Without that source block, accepting any of them would create
// contradictory admission authority before the raw create is
// either queued for a parent or assigned a residence lease.
return incoming.Position is null
&& incoming.SetupTableId is null
&& incoming.MotionState is null
&& incoming.MotionTableId is null
&& incoming.PhysicsState is null
&& incoming.ObjScale is null
&& incoming.Friction is null
&& incoming.Elasticity is null
&& incoming.InstanceSequence == 0
&& incoming.MovementSequence == 0
&& incoming.ServerControlSequence == 0
&& incoming.PositionSequence == 0
&& !hasTopParentGuid
&& incoming.PlacementId is null;
}
if (physics.Timestamps.Instance != incoming.InstanceSequence
|| physics.Timestamps.Position != incoming.PositionSequence
|| physics.Timestamps.Movement != incoming.MovementSequence
|| physics.Timestamps.ServerControlledMove
!= incoming.ServerControlSequence
|| physics.Position != incoming.Position)
return false;
PhysicsAttachment? flattenedParent = incoming.ParentGuid is { } parentGuid
&& incoming.ParentLocation is { } parentLocation
? new PhysicsAttachment(parentGuid, parentLocation)
: null;
if (flattenedParent != physics.Parent
|| incoming.PlacementId != physics.AnimationFrame)
{
return false;
}
return true;
}
private static bool IsStructurallyValidDeferredCreate(
in WorldSession.EntitySpawn incoming)
{
if (incoming.Guid == 0u)
return false;
if (incoming.Physics is not { } physics)
return true;
if (physics.Parent is null
&& physics.Position is { LandblockId: not 0u } position
&& !RuntimeAuthoritativePositionRouteClassifier
.IsValidCreateWirePosition(position))
{
return false;
}
if (physics.Velocity is { } velocity && !IsFinite(velocity)
|| physics.Acceleration is { } acceleration
&& !IsFinite(acceleration)
|| physics.AngularVelocity is { } angularVelocity
&& !IsFinite(angularVelocity)
|| physics.Scale is { } scale && !float.IsFinite(scale)
|| physics.Friction is { } friction && !float.IsFinite(friction)
|| physics.Elasticity is { } elasticity
&& !float.IsFinite(elasticity)
|| physics.Translucency is { } translucency
&& !float.IsFinite(translucency))
{
return false;
}
return true;
}
private bool AdmitSameGenerationCreate(
RuntimeEntityRecord canonical,
in RuntimeInitialCreateResidenceLease prior,
in WorldSession.EntitySpawn incoming,
in InboundCreateResult admitted,
bool isLocalPlayer)
{
if (!ReferenceEquals(
canonical,
Entities.TryGetActive(
incoming.Guid,
out RuntimeEntityRecord current)
? current
: null)
|| canonical.Incarnation != incoming.InstanceSequence
|| admitted.Disposition
is not CreateObjectTimestampDisposition.ExistingGeneration
|| !InitialCreateResidences.CanEnqueue(canonical, prior))
{
return false;
}
var actions = ImmutableArray.CreateBuilder<
RuntimeInitialCreateTailAction>();
RuntimeAcceptedPositionSource positionSource =
RuntimeAcceptedPositionSource.Unknown;
if (admitted.SameGenerationEvents is { } events)
{
actions.Add(new RuntimeInitialCreateTailAction(
RuntimeInitialCreateTailActionKind
.PreTailDescriptionAdaptation,
incoming.Guid,
Description: events.Description));
if (Entities.TryAcceptDeferredObjDesc(
events.Appearance,
out _))
{
actions.Add(new RuntimeInitialCreateTailAction(
RuntimeInitialCreateTailActionKind.ObjDesc,
incoming.Guid,
ObjDesc: events.Appearance));
}
if (events.Parent is { } parent)
{
if (Entities.TryAcceptDeferredCreateParent(
parent,
out _))
{
actions.Add(new RuntimeInitialCreateTailAction(
RuntimeInitialCreateTailActionKind.CreateParent,
incoming.Guid,
CreateParent: parent));
}
}
else if (events.Position is { } position)
{
if (!RuntimeAuthoritativePositionRouteClassifier
.IsValidCreateWirePosition(position.Position)
|| position.Velocity is { } velocity
&& !IsFinite(velocity))
{
return false;
}
if (!Entities.TryAcceptDeferredPosition(
position,
isLocalPlayer,
out PositionTimestampDisposition disposition,
out AcceptedPhysicsTimestamps timestamps,
out bool timestampMutation))
{
return false;
}
if (disposition is not PositionTimestampDisposition.Rejected
|| timestampMutation)
{
positionSource = RuntimeAcceptedPositionSource
.SameIncarnationCreate;
actions.Add(new RuntimeInitialCreateTailAction(
RuntimeInitialCreateTailActionKind.Position,
incoming.Guid,
Position: position,
PositionSource: positionSource,
PositionDisposition: disposition,
PreviousTeleportSequence:
timestamps.PreviousTeleport,
AcceptedTimestamps: timestamps,
HasTimestampMutation: timestampMutation));
}
}
else if (events.Pickup is { } pickup
&& Entities.TryAcceptDeferredPickup(pickup, out _))
{
actions.Add(new RuntimeInitialCreateTailAction(
RuntimeInitialCreateTailActionKind.Pickup,
incoming.Guid,
Pickup: pickup));
}
if (events.Movement is { } movement)
{
bool payloadApplied = Entities.TryAcceptDeferredMotion(
movement,
out AcceptedPhysicsTimestamps timestamps,
out bool timestampMutation);
if (payloadApplied || timestampMutation)
{
actions.Add(new RuntimeInitialCreateTailAction(
RuntimeInitialCreateTailActionKind.Movement,
incoming.Guid,
Movement: movement,
AcceptedTimestamps: timestamps,
AppliesMovementPayload: payloadApplied,
RetainMovementPayload: true,
HasTimestampMutation: timestampMutation));
}
}
if (Entities.TryAcceptDeferredState(events.State, out _))
{
actions.Add(new RuntimeInitialCreateTailAction(
RuntimeInitialCreateTailActionKind.State,
incoming.Guid,
State: events.State));
}
if (Entities.TryAcceptDeferredVector(events.Vector, out _))
{
actions.Add(new RuntimeInitialCreateTailAction(
RuntimeInitialCreateTailActionKind.Vector,
incoming.Guid,
Vector: events.Vector));
}
}
actions.Add(new RuntimeInitialCreateTailAction(
RuntimeInitialCreateTailActionKind.WeenieDescription,
incoming.Guid,
WeenieDescription: incoming));
actions.Add(new RuntimeInitialCreateTailAction(
RuntimeInitialCreateTailActionKind.ResidentCellCleanup,
incoming.Guid));
RuntimeInitialCreateResidenceLease retained = InitialCreateResidences
.EnqueueAccepted(
canonical,
prior,
RuntimeInitialCreateContinuationKind.SameIncarnationCreate,
positionSource,
actions.ToImmutable());
return retained.IsValid;
}
private void EnsureNotDisposed() =>
ObjectDisposedException.ThrowIf(_disposed, this);