Simple test node, close event never called?

I created a simple node example, just to test input and close events. The close event never seems to fire? Did I do something boneheaded here? The node works as expected, it get the input notification in log, but never seem to get the close notification in the log. Send works, in that I get output in debug as expected.

        function PiEnvironmentNode(config) {
                RED.nodes.createNode(this, config);
                var node = this;
                 //
                node.on('input', function(msg, send, done) {
                        //
                        try {
                                //
                                node.log('Input');
                                node.status(BLUE);
                                //
                                msg.payload = 'Pi Enviornment Node Under Construction';
                                send(msg);
                                //
                                setTimeout(() => { node.status(RESET); }, TIMEOUT);
                        } catch (theError) {
                                //
                                node.status(FAIL);
                                node.debug(theError);
                                if (done) {
                                        done(theError);
                                }
                        }
                });
                //
                node.on('close', function(done) {
                        //
                        node.log('Close');
                        node.status(RESET);
                        done();
                });
        }
        RED.nodes.registerType("pi-environment", PiEnvironmentNode);

If you modify the node in the node-red editor then deploy (or do a full deploy) you should get a close event.

Ok, maybe I don't understand the event model right? I got the close event on a full deploy I explicitly did. Thanks for the help. But if I just do an inject to my node, I will not get the close event every time? Oh... because the node is not deleted and recreated explicitly, right? The inject is just another input event.

New question then... is it required to call done, per input event? Per the documentation " The done function must be called when it has finished handling the message. It takes one optional argument, an error object if the node has failed to handle the message for some reason." I read this to include the input event. I don't see that in the examples I have seen thus far... using done seems to be still rare as the new methodology.

Yes. The input event is triggered when a node is passed a message. The handler is called, it does its work and when it has finished processing the message it must call the done function it was given.

It is true to say this new API style is not yet wide-spread. We're still working through the core nodes to add it in.

The close event is only triggered when the flows are stopping (because the runtime is stopping, or a new set of flows are being deployed).

Excellent! Again thanks. Really trying to get some good habits set here... been a solution designer, integrator, and coder at times for many years, but new to node-red. If it is a scripting language, I likely have used it at some point! Even HyperCard on Macintosh. (Don't tell anyone I know C, real C, as well... Does that date me? Oh well!).

how do i handle done events for something that works like the daemon node? so it starts a process and that process handles input and output. Do i call done when the long running process finishes or every time the process has an output in response to the message?

You should only call done once for a given message. When you call it will depend on what you think makes sense for the end user.... I think we're still figuring out for these sorts of edges cases what makes the most sense.

1 Like

The way I have my code setup right now, testing, evaluating design is along the following:

input->do something->success->send->done
input->do something->error->handle error->done
close->done

In a Sync or Async model the above is still consistent, say using spawned tasks. The only real difference with Async is if you have a timeout scenario.

input->do something->success->send->done
input->do something->error->handle error (non fatal resolve)->send->done
input->do something->error->handle error (fatal notify)->send (if applicable at all)->done
input->do something->timeout->handle timeout->send (if applicable at all)->done
close->done

A daemon is just a logical loop, persistent entity, that handles each input in turn.

But what if its not even if there is more than one output per input msg to the child from the child? Should you make the done dependent of a timeout? What if a message arrives from the child after that timeout but before a new input?

I believe you should not call done till all actions initiated by the input message are complete. Some nodes can never call done because the action is indefinite. Done is not important to the node-red system it is for the benefit of the user. For nodes where it is not relevant to call done then the user will presumably not be trying to catch it.

It was originally introduced for nodes like the e-mail node, so that the user could tell when the message had been sent (or failed to be sent).

1 Like

But having said that... once we have a larger critical mass of nodes that support done, then we will be able to introduce features like graceful shutdown of flows - where the runtime is able to stop accepting 'new' work, but allow existing work to complete before stopping everything (without appropriate timeouts for things that don't behave).

In the case of a long running process that isn't expected to stop - it may be that calling done once the process has successfully started is semantically the right thing to do.

As I said, I think we're still figuring this out a bit.

1 Like

Yes I see, so for ongoing action nodes then call done to say 'OK, got that, if you need to shut me down then any time is fine'.
This thread has come at a convenient time as it has reminded me that I need to implement done in a new node I am developing, it is the first node I have created since the new feature was introduced.

I keep reminding myself done is like memory cleanup in a heap... you do done when you are done... daemon or long loop process that handles many messages... is not done until fatal error or controlled exit.

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.