PulseEphemeralPolicy class
A governance policy that defines the Lifecycle Constraints and Termination Logic for a Pulse as it traverses the reactive graph.
In the reactive framework, PulseEphemeralPolicy implements the Signal Governance pattern. It prevents "Zombie Signals" and infinite propagation loops by establishing hard boundaries for both temporal duration (TTL) and topological distance (Hops).
Where to start
You create a pulse policy when you need a signal to self‑destruct after a certain time or after it has passed through too many nodes. Attach it to a pulse via Pulse.governed:
final policy = PulseEphemeralPolicy(
duration: Duration(seconds: 5),
onEvent: (cell, {required policy}) => (hops: 0),
onInvalidate: (pulse) => print('Pulse expired'),
);
final pulse = Pulse.governed<int>(payload: 42, policy: policy);
When to use
Use this when you need to:
- Ensure a command is only valid for a short window (e.g., one‑time tokens).
- Limit how far a signal can propagate to avoid infinite loops.
- Automatically clean up stale messages in a distributed system.
- Implement time‑based or hop‑based circuit breakers.
How it works
- The policy tracks the number of hops (node traversals) via
onEvent. - It starts a TTL timer on the first interaction with any cell.
- When either the hop limit or the TTL is exceeded, the
onInvalidatecallback is triggered, and the pulse is marked as invalid. - Invalidation is checked automatically by the framework before processing a pulse; invalidated pulses are silently dropped.
- The policy is stateless except for the hop counter and invalidation flag, which are stored in a lightweight record.
Non‑obvious
- The TTL timer starts lazily – only when the pulse first interacts with a cell, not at creation time. This avoids unnecessary timers for pulses that are never propagated.
- If both
durationandhopLimitare set, the policy invalidates as soon as either condition is met. - The
onEventcallback must return a({int? hops})record. Returningnullforhopsmeans no hop increment (useful for resetting counters). - The policy is attached to a specific pulse instance; it does not affect the cell's lifecycle policy.
- The
onInvalidatecallback receives the invalidated pulse – you can use this for logging, cleanup, or triggering compensatory actions.
Example: Time‑Sensitive Authentication Token
final authPolicy = PulseEphemeralPolicy(
duration: Duration(minutes: 5),
onEvent: (cell, {required policy}) => (hops: 0),
onInvalidate: (pulse) {
print('Token expired. Re‑authenticate.');
return true;
},
);
final tokenPulse = Pulse.governed<String>(
payload: 'session_123',
policy: authPolicy,
);
Example: Hop‑Limited Broadcast
final broadcastPolicy = PulseEphemeralPolicy(
hopLimit: 3,
onEvent: (cell, {required policy}) => (hops: policy.hops + 1),
onInvalidate: (pulse) => print('Broadcast stopped after 3 hops'),
);
See also:
- Pulse.governed – the factory that attaches a policy to a pulse.
- EphemeralPolicy – the cell‑level lifecycle policy (similar, but for cells).
Constructors
- PulseEphemeralPolicy({required ({int? hops}) onEvent(Cell cell, {required PulseEphemeralPolicy policy}), required bool onInvalidate(Pulse element), int? hopLimit, Duration? duration, dynamic user})
- Creates a new PulseEphemeralPolicy with the specified lifecycle constraints.
Properties
- duration → Duration?
-
The maximum Time‑To‑Live (TTL) for the pulse.
no setter
- hashCode → int
-
The hash code for this object.
no setterinherited
- hopLimit → int?
-
The maximum number of node transitions (hops) permitted.
no setter
- hops → int
-
The current number of nodes traversed in the causal chain.
no setter
- isInvalidated → bool
-
Returns
trueif the pulse has been invalidated.no setter - runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
Methods
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
toString(
) → String -
A string representation of this object.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited