feat(runtime): expose dormant placement receipts
This commit is contained in:
parent
4c02ac4259
commit
270f5154b9
9 changed files with 223 additions and 4 deletions
|
|
@ -0,0 +1,88 @@
|
|||
using AcDream.Runtime.Entities;
|
||||
|
||||
namespace AcDream.Runtime.Physics;
|
||||
|
||||
/// <summary>
|
||||
/// Public host boundary for Runtime-owned SetPosition projection receipts.
|
||||
/// The channel owns no placement state: observation, retry, and exact-token
|
||||
/// acknowledgement delegate to the canonical entity lifetime's event stream
|
||||
/// and SetPosition owner.
|
||||
/// </summary>
|
||||
public sealed class RuntimePlacementProjectionChannel
|
||||
{
|
||||
private readonly RuntimeEntityObjectEventStream _events;
|
||||
private readonly RuntimeSetPositionState _setPosition;
|
||||
private Func<RuntimeGenerationToken> _generation = static () => default;
|
||||
private bool _generationBound;
|
||||
|
||||
internal RuntimePlacementProjectionChannel(
|
||||
RuntimeEntityObjectEventStream events,
|
||||
RuntimeSetPositionState setPosition)
|
||||
{
|
||||
_events = events ?? throw new ArgumentNullException(nameof(events));
|
||||
_setPosition = setPosition
|
||||
?? throw new ArgumentNullException(nameof(setPosition));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Observes ordered immutable projection receipts on the Runtime commit
|
||||
/// thread. A host must acknowledge only after its projection succeeds.
|
||||
/// </summary>
|
||||
public IDisposable Subscribe(IRuntimePlacementObserver observer) =>
|
||||
_events.SubscribePlacement(observer);
|
||||
|
||||
internal void BindGeneration(Func<RuntimeGenerationToken> generation)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(generation);
|
||||
if (_generationBound)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"The Runtime placement generation source is already bound.");
|
||||
}
|
||||
|
||||
_generation = generation;
|
||||
_generationBound = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Acknowledges only the exact oldest outstanding receipt. Stale,
|
||||
/// reordered, superseded, or already acknowledged tokens are rejected.
|
||||
/// </summary>
|
||||
public bool Acknowledge(
|
||||
RuntimeGenerationToken expectedGeneration,
|
||||
in RuntimePlacementProjectionToken token) =>
|
||||
IsCurrent(expectedGeneration)
|
||||
&& _setPosition.AcknowledgeProjection(token);
|
||||
|
||||
/// <summary>
|
||||
/// Republishes every still-pending immutable receipt in canonical order.
|
||||
/// Runtime authority is never replayed or recommitted by a retry.
|
||||
/// </summary>
|
||||
public bool RetryPending(RuntimeGenerationToken expectedGeneration)
|
||||
{
|
||||
if (!IsCurrent(expectedGeneration))
|
||||
return false;
|
||||
_setPosition.RetryPendingProjections();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the exact oldest outstanding receipt without consuming it.
|
||||
/// </summary>
|
||||
public bool TryPeek(
|
||||
RuntimeGenerationToken expectedGeneration,
|
||||
out RuntimePlacementProjectionSnapshot projection)
|
||||
{
|
||||
if (IsCurrent(expectedGeneration))
|
||||
return _setPosition.TryPeekProjection(out projection);
|
||||
projection = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
public int PendingCount => _setPosition.PendingProjectionCount;
|
||||
|
||||
private bool IsCurrent(RuntimeGenerationToken expectedGeneration) =>
|
||||
_generationBound
|
||||
&& expectedGeneration.Value != 0UL
|
||||
&& expectedGeneration == _generation();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue