Skip to content
mchristegh edited this page Jul 10, 2026 · 2 revisions

Every message the node emits carries msg.timerEvent naming what happened — or what was attempted. This page is the complete vocabulary. The envelope those events ride on is documented in Output Messages.

The taxonomy

Event Output(s) Can be ignored: true? source
counted 3 Yes — a candidate blocked by cooldown or disabled external
triggered 1 + 3 No external
windowexpired 3 No internal
stopped 3 Yes — stop while idle external
reset 3 Yes — reset while idle or during cooldown external
disabled 3 Yes — redundant disable external
enabled 3 Yes — redundant enable external
countlimitset 3 Yes — invalid value external
windowset 3 Yes — invalid value external
query 2 No external or internal
cooldownstarted 3 No internal
cooldownended 3 No internal

The design philosophy: ignored is a modifier, not a category

There is no separate "blocked message" event type. A candidate discarded during cooldown is still labeled counted — with ignored: true. A redundant disable is still labeled disabled. The event type always tells you what was attempted; the ignored flag tells you whether it took effect. This means a downstream switch node on msg.timerEvent sees a complete, uniform record of everything that arrived, and a second check on msg.ignored separates the real from the rejected.

Event reference

counted

A candidate incremented the count — or tried to. The genuine form (ignored: false) fires on output 3 with msg.count showing the new total. There is no separate "cycle started" event: the first message of a cycle is an ordinary counted with count: 1 and timerState newly counting. The blocked form (ignored: true) marks a candidate discarded by Cooldown or the disabled flag.

One deliberate gap: the candidate that completes the count does not emit counted — it emits only triggered. Counting counted events per cycle therefore yields limit − 1.

triggered

The count reached the limit. Fires exactly once per cycle, immediately, on outputs 1 and 3 — the node never waits for the window to close. The message is a clone of the completing candidate (payload and topic carry through), and its envelope reports the settled post-trigger state; see Output Messages. A setcountlimit that lowers the limit to at or below the live count also produces this event.

windowexpired

The counting → idle transition without a Trigger. One event name covers both modes — fixed: the shared window closed; sliding: the count decayed to zero. msg.windowMode distinguishes them. Sliding intermediate decay (count dropping but not to zero) emits nothing — it is observable only via status, query, or Heartbeat. Always source: "internal": expiry is the node's own clock, never a message.

stopped / reset

The two cycle-clearing commands. Their genuine and ignored conditions, and the one situation where they differ (cooldown), are detailed on Input Messages.

disabled / enabled

The counting gate toggling — or a redundant attempt (ignored: true). The flag itself rides on every message as msg.disabled.

countlimitset / windowset

Runtime configuration changes — or invalid attempts (ignored: true). Both carry an extra property (msg.countLimitSet / msg.windowSet) holding the applied or rejected value. A windowset on a live cycle can be immediately followed by windowexpired if the new window has already elapsed; a countlimitset can be immediately followed by triggered. In both cases the set event dispatches first, so the event stream reads causally.

query

A state snapshot on output 2 — the only event that never appears on output 3. source: "external" for a requested query, source: "internal" for a Heartbeat tick; the two are otherwise identical in shape.

cooldownstarted / cooldownended

The cooldown bracket, both internal. cooldownended does not re-fire the Trigger — that was already reported once when the count hit the limit. A cooldown cancelled by stop emits stopped, not cooldownended. Full lifecycle on Cooldown.

Sequences worth knowing

What the Events output emits for common scenarios (limit 3 unless noted):

  • Normal trigger: counted (1)counted (2)triggered
  • Trigger into cooldown:triggeredcooldownstarted(blocked candidates: counted ignored:true)cooldownended
  • Fixed window runs out: counted (1)counted (2)windowexpired
  • Sliding decay: counted (1)counted (2)(silence as the count decays to 1)windowexpired (only at zero)
  • Limit lowered mid-cycle (3 → 2 with 2 counted): countlimitsettriggered

Clone this wiki locally