Class EmissionGate

java.lang.Object
com.framed.interop.gate.EmissionGate

public final class EmissionGate extends Object
Per-key outbound emission throttle. Keeps interoperability traffic at clinical cadence so the raw high-frequency stream never reaches a downstream system.

State is held per key. The key must identify one logical signal: callers that serve multiple devices through a single gate instance must include the device id in the key (e.g. "<deviceID>.<channelID>"), otherwise identically named channels on different devices share one throttle slot and suppress each other.

Two independent filters, both applied when enabled; a value is emitted only if it passes both:

  • minIntervalMs — at most one emission per key per interval;
  • onChange — suppress repeats of the last emitted value for a key.

Checking and committing are separate steps: allows(java.lang.String, java.lang.Object, long) is a side-effect-free check; the two filters' state is committed independently. Callers performing fallible I/O should commitAttempt(java.lang.String, long) the interval state when they start an emission attempt (so a failing endpoint is probed at most once per interval instead of once per sample) and commitValue(java.lang.String, java.lang.Object) the onChange state only after the receiver accepted the value (so a failed or rejected send does not suppress an identical follow-up value). commit(java.lang.String, java.lang.Object, long) does both at once; allow(java.lang.String, java.lang.Object, long) combines check and full commit for callers whose emission cannot fail after the check. The check-then-commit pair is not atomic; concurrent callers may occasionally both pass the check, which for a throttle is an acceptable extra emission (never a loss).

With both filters disabled the gate is a pass-through. The clock is supplied by the caller so behaviour is deterministic in tests.

  • Constructor Details

    • EmissionGate

      public EmissionGate(boolean onChange, long minIntervalMs)
      Parameters:
      onChange - if true, suppress consecutive equal values per key
      minIntervalMs - minimum milliseconds between emissions per key (0 disables the filter)
  • Method Details

    • passthrough

      public static EmissionGate passthrough()
      A pass-through gate that never suppresses.
    • keyFor

      public static String keyFor(String deviceID, String channelID)
      The canonical device-scoped emission key (see class doc). All callers gating bus datapoints must build their key through this method so identically named channels on different devices never share a throttle slot.
      Parameters:
      deviceID - the device id
      channelID - the channel id
      Returns:
      the emission key "<deviceID>.<channelID>"
    • allows

      public boolean allows(String key, Object value, long nowMs)
      Checks whether value on key may be emitted now, without recording anything.
      Parameters:
      key - the emission key (device-scoped, see class doc)
      value - the latest value
      nowMs - the current time in epoch millis
      Returns:
      true if the value passes both filters
    • commitAttempt

      public void commitAttempt(String key, long nowMs)
      Records an emission attempt on key: only the interval filter's state. Call when starting a fallible emission, before its outcome is known — during an endpoint outage this throttles attempts to one per interval instead of one per sample, without affecting the onChange filter.
      Parameters:
      key - the emission key
      nowMs - the attempt time in epoch millis
    • commitValue

      public void commitValue(String key, Object value)
      Records a delivered value on key: only the onChange filter's state. Call only after the receiver accepted the value, so a failed or rejected send does not suppress an identical follow-up value.
      Parameters:
      key - the emission key
      value - the delivered value (null is ignored)
    • commit

      public void commit(String key, Object value, long nowMs)
      Records a completed emission of value on key: both filters' state at once (commitAttempt(java.lang.String, long) + commitValue(java.lang.String, java.lang.Object)).
      Parameters:
      key - the emission key
      value - the emitted value
      nowMs - the emission time in epoch millis
    • allow

      public boolean allow(String key, Object value, long nowMs)
      Convenience for infallible emissions: checks and, when allowed, immediately commits.
      Parameters:
      key - the emission key
      value - the latest value
      nowMs - the current time in epoch millis
      Returns:
      true if the value should be emitted