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 onInvalidate callback 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 duration and hopLimit are set, the policy invalidates as soon as either condition is met.
  • The onEvent callback must return a ({int? hops}) record. Returning null for hops means 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 onInvalidate callback 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 true if 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

Static Methods

mask({required Function onEvent, required Function onInvalidate, int? hopLimit, Duration? duration, dynamic user}) → Record