[ANNOUNCE] node-red-semaphore-plus


Before I begin:

I have seen so many flows/solutions/subflows that aim to bring semaphore features to a flow, but.... they all have 1 or more things in common.

  • They are no longer maintained (and therefore have undesirable bugs)
  • Involves using nodes that are not really designed for managing access to a resource (therefore become messy)
  • don't have some form of fail-safe in mind.

I needed all of this!

Introducing node-red-semaphore-plus

Uh... what is it

This is a set of Nodes for Node RED, that allows messages to be queued, and signalled to pass, once a message has reached the end of the flow.
But at the same time, allowing an optional fail-safe, that can be controlled dynamically.

Node What's it for?
Semaphore Take Queues and passes a message through when signalled (or when the optional fail-safe triggers)
Semaphore Release Raises the signal to allow a message to pass
Semaphore FS Reset Alters the current fail-safe time

The fail-safe time is set at Node level (Semaphore Take, Semaphore FS Reset),
But! You can also pass in a msg property of sp_timeout and the nodes will ignore what is set at Node level, and use this value instead

Setting the fail-safe to 0 (zero) will disable the fail-safe, meaning Semaphore Release will be the only node that can release the lock

If nothing has already taken the lock, the message will of course pass through, and subsequently start queuing other messages, where each one is allowed to pass on the signal or fail-safe trigger

Messages are released with a property of sp_isFailsafe, and this lets you know if the release was due to a fail-safe condition


I hope you enjoy - please do comment


V2 is up - This addresses some initial teething issues, and renames the properties.

msg.smp_isFailsafe :
Denotes whether the message taking the lock was due to a fail safe condition

msg.smp_failsafeTimeout :
Dynamically controls the fail-safe time for a message entering the lock, or when using The FS Reset Node

Thank you for this. I expected a greater response to your post, but I think many of us will find your nodes very useful.

Just a few suggestions for possible improvements:

  • Improve the documentation. The .html file should include text that appears when one of the nodes is selected in the palette and the help pane in the sidebar. In particular, the node status should be described. The meanings of GQ and LQ are not obvious. LFS presumably refers to the fail-safe, but what does the L mean?

  • Provide a reset command that deletes the queue and restores the semaphore. This may not be important in operation but could help in development and debugging.

  • I think there should be an option to limit the size of the queue. This could be done in the node configuration or by having the node use the nodeMessageBufferMaxLength parameter defined in settings.js.

Thanks again for your effort.

1 Like

Hi Mike,

Thanks for the feedback!

I fully agree with the documentation, I developed this to solve some specific problems in work, that needed addressing quickly, so may have cut corners on the docs :innocent: - I’ll get them improved on the next update.

LFS - Last Fail Safe time that was used
QG - Global Queue size
LQ - Local Queue size

I also like the suggestions with the queue size and purge commands, Watch this space :nerd_face:

1 option I hoped it would have is to limit the queue to 1 and either discard the msg, raise an error or output the msg on a second output.

I would use the first option (limit and discard) like a gate

I would use the 2nd option for times where it is an unexpected condition to have multiple messages arrive in succession

And use the last option for kinda scaling out where one flow is busy, the message can be passed to another flow.

Lastly, I haven't checked but do your nodes place nice with the catch and complete nodes?

1 Like

Hi Steve,

The nodes do indeed employ done() so should work with the complete node, as for catch - nothing is actively handled presently.

It's extremely funny you mentioned a 2nd output, as I have been teasing this idea, and how best to utilise a 2nd output - some room for some handy processing here.

As for a limit - this will be implemented, and may Evan employ the 2nd output pin somehow, almost like an overflow drain

All great ideas coming in :slightly_smiling_face:

1 Like

Based on the feedback thus far.
I think I have come up with something that could work really well.

Option will be:

  • msg.smp_avoidQueue
  • Never
  • Threshold

Example: If the flow is busy (lock engaged), but you need to allow a message to pass, you would set the Avoidance Mode accordingly, and attach a message part of msg.smp_avoidQueue: true, the message will then pass through Pin 2 avoiding the semaphore queue.

With Threshold its the same, but only if the queue is at the Threshold (no need for smp_avoidQueue)

I'm still playing with ideas

I am not a fan of magic msg properties.

For control type messaging - the 2 options I explore before resorting to a magic prop is

  1. Use a topic and payload arrangement for control messages
    • e.g. { topic: 'smp:avoid-queue', payload: 'never' }
    • this has the benefit of being both explicit AND everyone (the programmer, we the user) know and expect a control message to NOT be considered a real message that needs to be processed / passed on.
  2. TypeInput - this makes it immediately clear to the user which msg prop is used (and have the freedom to change it)
1 Like

I like it a lot :slight_smile:

I might play with using typed inputs, as using a single message to alter its behaviour, will alter it for all messages, I want to allow 'priority' messages to be given a free pass, hence the magic prop - but I will move that to a user definable typed input.

Very Nice - thanks!

1 Like