Skip to content

Persistent-effect scheduler architecture

Mass Forge schedules finite lifetimes and periodic effects through one world-local deadline min-heap. The scheduler is owned by the fixed-order gameplay coordinator's Persistent Effects phase; it is not an independently ticking system and does not walk every Mass entity or every entity carrying the Persistent Effects fragment.

Runtime model

Each active persistent handle has one central schedule record containing its last logical update time and a monotonically changing revision. A finite expiration, a periodic pulse, or pending catch-up work contributes one next-deadline entry to the heap. Infinite non-periodic markers retain a schedule record for query and ownership consistency but require no heap entry.

The authoritative lifecycle slot remains fixed-capacity fragment data on the entity. Time is advanced lazily when its deadline is reached, when a refresh or extension must modify it, or when a public query projects its visible state. The query projection uses a copy and never changes the schedule.

The schedule clock advances only from valid scaled gameplay delta supplied by the coordinator. When Mass owns the entity manager, elapsed delta is deferred to the next safe phase. World pause, global time dilation, teardown, and save behavior therefore remain those defined in the time, travel, and save contract.

Deadline and rescheduling rules

The next deadline is the earliest of:

  • the next periodic boundary;
  • the finite expiration boundary; or
  • the current scheduler time when earned pulse backlog or expiration cleanup is pending.

Refresh, extension, replacement, cancellation, manual removal, and ability rollback all update or retire the central schedule atomically with the lifecycle state. Rescheduling increments the handle's revision and pushes a new entry. An older entry can remain in the heap temporarily, but its stale revision can never execute gameplay. Stale entries are discarded when reached, and the heap is rebuilt when lazy entries exceed a bounded ratio to active schedules.

One due instance executes at most 64 earned pulses in a phase. Any remaining backlog receives an immediate next deadline and drains over later phases. A finite effect expires only after all pulses earned inside its lifetime have been attempted.

Determinism and callbacks

Heap layout is not observable gameplay order. Due handles are sorted by complete entity identity—index and serial number—and then persistent handle ID before work is published. Period numbers remain ascending, earned pulses precede same-boundary expiration, and a listener that removes a later captured instance suppresses that instance's remaining publication. The full cross-system order is in the deterministic gameplay ordering contract.

Destroyed-owner cleanup intentionally checks active persistent handles once per scheduler phase, including a zero-delta phase. This is proportional to active effects, not total Mass population, and preserves generation-safe retirement without requiring an entity-world scan. The lifecycle rules are in the entity lifecycle safety contract.

Blueprint diagnostics

Use Get Persistent Effect Scheduler Stats on the Mass Forge Persistent Effect subsystem to read an on-demand Mass Forge Persistent Effect Scheduler Stats value:

FieldMeaning
ActiveEffectCountActive lifecycle handles.
TimerHeapEntryCountCurrent heap entries, including lazy stale entries.
ScheduledEffectCountActive central schedule records.
DueEffectCountLastTickCurrent-revision handles whose deadline was processed in the most recent phase.
ValidityCheckCountLastTickActive owner handles checked in the most recent phase.
StaleHeapEntryCountLastTickObsolete revisions discarded in the most recent phase.

These counters are diagnostics, not a frame-rate benchmark. A refresh can temporarily make TimerHeapEntryCount greater than ScheduledEffectCount; that is expected lazy invalidation. Sustained growth beyond the documented compaction ratio is a support signal.

Verification contract

Release verification applies three independent checks:

  1. A source gate requires the deadline-heap operations and rejects Mass entity query, chunk traversal, or entity-iterator APIs inside the bounded scheduler region.
  2. MassForge.PersistentEffects.DeadlineHeapScaling creates 512 unrelated entities and proves one active effect performs one ownership-validity check, not population-sized work. It also covers refresh rescheduling, stale-entry rejection, query projection, exact pulse execution, removal, and lazy cleanup.
  3. The complete suite runs twice from the packaged plugin under every advertised Unreal Engine baseline, in addition to strict Editor, Development Game, and Shipping Game builds.

This architecture removes population-wide timer scans. It does not by itself claim a particular 10k, 100k, or 1M throughput; those figures require the separate reference-hardware benchmark gate.

Mass Forge documentation — generated from the shipping Markdown source.