node-red-contrib-join-wait 0.6.3

Node-RED node that joins related messages across multiple paths within a time window — with exact-order matching, regex paths, correlation grouping, reset paths, and queue persistence. Coordinate parallel flows, synchronize events, and debounce sensors.

npm install node-red-contrib-join-wait

node-red-contrib-join-wait

CI npm npm downloads license

A Node-RED node that joins related messages across multiple paths within a time window — with exact-order matching, regex paths, correlation grouping, reset paths, and queue persistence. Coordinate parallel flows, synchronize events, and debounce sensors.

If all the named paths arrive in time, a merged message is emitted on the success output. Anything left over goes to the expired output for optional follow-up.

Use cases

  • Debounce a motion sensor when a light turning on/off is also tripping it: only fire if light_off then motion then light_on all arrive within 10 s.
  • Correlate request lifecycle events — wait for request_started and request_finished with the same correlation id and emit one log entry with the duration.
  • Sensor consensus — only act when both door_open and vibration fire within 2 s.
  • Recombine fanned-out API calls — join the responses from a split flow when each branch tags its result with a known path name.
  • Watchdog gate — let start plus N progress beats arrive within a window, otherwise route to an alarm flow via the expired output.

Is this the right node? join-wait vs. the stock join node

You need to… Stock join join-wait
Recombine pieces of a split message (msg.parts)
Concatenate strings, arrays, or buffers
Count "any N messages" into a batch
Wait for specific named paths within a time window
Match path names by regex
Require an exact order (with repeats)
Drain the queue when a "reset" path arrives
Group by an arbitrary correlation expression

Rule of thumb: if you split a message and want to put it back together, use the stock join. If you have heterogeneous events from different sources and want to coordinate them, use join-wait.

Quick start

cd ~/.node-red
npm install node-red-contrib-join-wait

Or search join-wait in Manage palette → Install.

Open the editor, drag a join-wait node onto a flow, and add the path names you want to wait for. That's it.

Looking for a working flow? After install, open Menu → Import → Examples → join-wait for ready-made flows.

Tip: in the Wait paths / Reset paths lists you can press Enter in a row to add the next one, and paste newline-separated text into any row to fill the current row and append the rest as new rows — handy for seeding a list from a spreadsheet column or a debug log.

How it works

              ┌──────────────┐
input  ───►   │   join-wait  │  ───► (1) success — merged msg
              └──────────────┘  ───► (2) expired — anything that didn't make it

Every incoming message tells the node which path it represents (via a configurable message property — msg.topic by default). The node holds onto each one until either:

  • All wait paths arrive within the timeout → forwards a single merged message on output 1.
  • The timeout elapses, or a reset path is seen, or msg.complete is set → forwards whatever's queued to output 2.

Configuration

Field What it controls
Path field The msg property whose value names the path. Default msg.topic. Can be a string or an object of paths.
Wait paths The path names to wait for. Repeating an entry means "this path must arrive that many times".
Timeout Window for all wait paths to arrive.
Match order Any order (default) or Exact order.
Group by Optional — only joins messages whose value at this property matches. Use msg._msgid for split-flow joins.
Output base Use the first or last received message as the base of the merged output.
Merge values Keep original path values, or overwrite each with that message's msg.payload.

Advanced

Field What it controls
Reset paths Path names that immediately drain the queue to the expired output. Each must be unique.
Use regex Treat each path entry as a regular expression.
Unmatched paths Log a warning when a message arrives with a path not in either list.
Ignore complete Disable the msg.complete short-circuit.
Preserve queue Keep the queue across deploys and (with a configured store) restarts.
Persist store Name of a context store from settings.js (e.g. localfilesystem) for restart persistence.

Per-message overrides

Any of these on an incoming message change behavior for that message only (no node-level state is persisted):

  • msg.pathsToWait — array overriding Wait paths.
  • msg.pathsToExpire — array overriding Reset paths.
  • msg.useRegex — boolean overriding Use regex.
  • msg.complete — drains the queue to the expired output.
  • msg.reset (boolean true) — silently drains the queue, no output.

Path field as a string vs. object

// As a string — one path per message
msg.topic = 'path_1';

// As an object — one message represents multiple paths
msg.topic = { path_1: true, path_2: true };

// As an object — values are kept in the merged output (when "Merge values"
// is set to keep original)
msg.topic = { path_1: { sensor: 'A' }, path_2: { sensor: 'B' } };

Behavior reference

  • When the same wait path arrives more than required, only the latest value is kept in the merged output.
  • In Exact order mode, unexpected paths between expected ones are tolerated.
  • In any-order mode with regex, paths are counted greedily left-to-right. ["path_[12]", "path_2"] will never complete because every path_2 arrival gets attributed to the first regex.
  • Pad Timeout with a small overhead (~5–10 ms) when working with very short windows — evaluation isn't free.
  • The success output reuses the chosen base message (first or last) and attaches the merged data on the Path field property.

Persistence

Queues live in Node-RED's context store. Preserve queue is on by default, so partial joins survive a redeploy out of the box (the default in-memory store keeps state in-process).

To survive full Node-RED restarts, configure a persistent context store in settings.js. The simplest setup:

contextStorage: {
    default: { module: 'localfilesystem' },
}

Every join-wait node then uses the default store automatically.

If you have a mixed setup with memory as the default and a separate persistent store (e.g. for archival), join-wait is smart about it: when Preserve queue is on but the default store is memory, the node auto-picks the first non-memory named store and logs which one it chose. So this configuration also gets restart persistence for free:

contextStorage: {
    default: { module: 'memory' },
    file:    { module: 'localfilesystem' },  // auto-picked
}

Set Persist store explicitly on a node to override the auto-pick.

Example flows

After install, Menu → Import → Examples → join-wait lists ready-made flows:

  1. Quickstart — wait for two paths within 5 s.
  2. Correlation — group messages from a split flow via _msgid.
  3. Reset paths — abort the queue when a reset path arrives.
  4. Regex paths — match path names by regular expression.
  5. Exact order — require a specific sequence (with a repeated step).

Compatibility

  • Node-RED 3.x and 4.x.
  • Node.js 20 / 22 / 24.

Migrating from 0.5.x

Version 0.6 is mostly drop-in compatible, with two intentional behavior tweaks:

  • msg.pathsToWait, msg.pathsToExpire, and msg.useRegex are now one-shot overrides — they affect only the current message and no longer mutate the node's stored config.
  • Persistence moved from a node-persist singleton to Node-RED's context store (fixes a multi-node race). For restart persistence, configure a persistent store in settings.js and set Persist store.

The configuration field for paths now stores a real array; the legacy JSON string form ('["a","b"]') is still accepted at runtime so existing flows keep working without re-deploying.

See CHANGELOG.md for the full list of changes.

Contributing

Issues and PRs welcome — please run npm test, npm run lint, and npm run spellcheck locally before sending.

Support this project

If this project saved you time and you'd like to send a tip:

  • PayPal — one-time PayPal donations.

  • Venmo — one-time donations via Venmo:

    Venmo QR

A GitHub star also goes a long way.

License

MIT — see LICENSE.

Credits

Originally inspired by mauriciom75/node-red-contrib-wait-paths.

Node Info

Version: 0.6.3
Updated 1 week, 3 days ago
License: MIT
Rating: 4.3 6

Categories

Actions

Rate:

Downloads

255 in the last week

Nodes

  • join-wait

Keywords

  • node-red
  • node-red-contrib
  • join
  • merge
  • wait
  • timeout
  • parallel
  • synchronize
  • coordinate
  • correlate
  • correlation
  • barrier
  • gate
  • aggregate
  • sequence
  • debounce
  • regex
  • pattern
  • events
  • iot
  • home-automation

Maintainers