mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Updated Design: Node Messaging API (markdown)
parent
d2cb10e3f1
commit
b9fe4741e4
@ -25,9 +25,61 @@ This simple system has a few limitations that we want to address:
|
|||||||
|
|
||||||
This design note explores how this mechanism could be updated to satisfy these limitations.
|
This design note explores how this mechanism could be updated to satisfy these limitations.
|
||||||
|
|
||||||
|
The original draft of this node set out three options. Through the process of writing the options, I've chosen my preferred approach. I have left the other two options at the bottom of the note for reference.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Option 1: Add a `node.complete` function - v1
|
### Pass in scoped `send` and `done` functions
|
||||||
|
|
||||||
|
If the event handler is registered with three arguments, the runtime will pass in functions that should be used to send or mark the msg as handled.
|
||||||
|
|
||||||
|
```
|
||||||
|
this.on('input', function(msg, send, done) {
|
||||||
|
// do something with 'msg'
|
||||||
|
if (!err) {
|
||||||
|
// send can be called as many time as needed (including not at all)
|
||||||
|
send(msg);
|
||||||
|
send(msg);
|
||||||
|
send(msg);
|
||||||
|
// Once complete, done is called
|
||||||
|
done();
|
||||||
|
} else {
|
||||||
|
// If an error occurs, call done providing the error.
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
The `done` function takes two arguments: `done(error, message)`.
|
||||||
|
|
||||||
|
|
||||||
|
Usage | Meaning
|
||||||
|
-----------------|------------
|
||||||
|
`done()` | success. Any `success` node targeting this node will be triggered using the original msg
|
||||||
|
`done(null,msg)` | success. Any `success` node targeting this node will be triggered using the provided msg
|
||||||
|
`done(err)` | failure. Any `catch` node targeting this node will be triggered using the original msg
|
||||||
|
`done(err,msg)` | failure. Any `catch` node targeting this node will be triggered using the provided msg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- a new node will be added to compliment the `Catch` node that can be used to trigger a flow when a node finished processing a message. It's current name is the `Success` node - but it needs to change.
|
||||||
|
- this feels the most 'node.js-like'. The presence of a `done` callback is familiar to many apis.
|
||||||
|
- the functions can be scoped to the received message so the node does not need to provide the message back
|
||||||
|
- the runtime can tell if the handler expects these extra arguments or not, so can adapt its behaviour to match
|
||||||
|
- `node.send` should not be used in this case as its use will stop the runtime from being able to correlate message received with message sent. We _probably_ won't enforce this - tbd.
|
||||||
|
- `node.error` can still be used as a handler may need to log multiple errors before completing.
|
||||||
|
|
||||||
|
**What if `done` is never called?** - If a handler is registered that takes the `send` and `done` arguments, the runtime requires it to eventually call `done` for each message received. Not calling `done` should be considered a bug with the node implementation. The question is what happens if it doesn't get called.
|
||||||
|
|
||||||
|
The easy option is to do nothing. But that will allow buggy implementations to exist, so we should avoid this option.
|
||||||
|
|
||||||
|
The right approach will be to timeout the function. A timeout would be considered an error and logged as such. The runtime will set a default timeout of **30 seconds (TBD)**. A node will be able to set its own timeout value by setting a property on itself (`this.TIMEOUT = 60000` (TBD)). This also allows a future extension where a user can set custom timeout values per node in the editor (but this proposal does not extend that far today).
|
||||||
|
|
||||||
|
**What if a node that has been timed out then wakes up and calls `done` or `send`?** - should the runtime then block a timed out node from calling `send` or `done` (at least... prevent any messages it then sends from being passed on? I can see use cases for both allowing the message to pass on and for stopping it. Does this need to be a per-node policy? Or a choice made in the editor? Hmmm.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Alternative Option 1: Add a `node.complete` function - v1
|
||||||
|
|
||||||
The first proposal is to add a new function to the Node object that can be called when a node has finished handling a message.
|
The first proposal is to add a new function to the Node object that can be called when a node has finished handling a message.
|
||||||
|
|
||||||
@ -46,7 +98,7 @@ this.on('input', function(msg) {
|
|||||||
- this relies on the user passing msg through - something that could be a source of programming error.
|
- this relies on the user passing msg through - something that could be a source of programming error.
|
||||||
- it would need clear semantics over when it was called and how it relates to `node.error`.
|
- it would need clear semantics over when it was called and how it relates to `node.error`.
|
||||||
|
|
||||||
### Option 2: Add a `node.complete` function - v2
|
### Alternative Option 2: Add a `node.complete` function - v2
|
||||||
|
|
||||||
The second proposal is similar to the first, but the `complete` function can also be used to indicate a failure:
|
The second proposal is similar to the first, but the `complete` function can also be used to indicate a failure:
|
||||||
|
|
||||||
@ -68,31 +120,3 @@ this.on('input', function(msg) {
|
|||||||
- this relies on the user passing msg through - something that could be a source of programming error.
|
- this relies on the user passing msg through - something that could be a source of programming error.
|
||||||
- it would need clear semantics over when it was called and how it relates to `node.error`.
|
- it would need clear semantics over when it was called and how it relates to `node.error`.
|
||||||
|
|
||||||
|
|
||||||
### Option 3: Pass in scoped `send` and `done` functions
|
|
||||||
|
|
||||||
If the event handler is registered with three arguments, the runtime will pass in functions that should be used to send or mark the msg as handled.
|
|
||||||
|
|
||||||
```
|
|
||||||
this.on('input', function(msg, send, done) {
|
|
||||||
// do something with 'msg'
|
|
||||||
if (!err) {
|
|
||||||
send(msg);
|
|
||||||
send(msg);
|
|
||||||
send(msg);
|
|
||||||
done(null, msg);
|
|
||||||
} else {
|
|
||||||
// Log the error, but don't provide the msg obj here
|
|
||||||
node.error(error1);
|
|
||||||
node.error(error2);
|
|
||||||
node.error(error3);
|
|
||||||
done(err, msg);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
- this feels the most 'node.js-like'. The presence of a `done` callback is familiar to many apis. Calling it
|
|
||||||
without an argument is considered success, with an argument is considered failure.
|
|
||||||
- the functions can be scoped to the received message so the node does not need to provide the message back
|
|
||||||
- the runtime can tell if the handler expects these extra arguments or not, so can adapt its behaviour to match
|
|
||||||
- need to consider whether the node should still be allowed to use `node.send` and `node.error` directly. It would be possible to disable either of these functions if we see this new style message handler registered. There is certainly a case to support `node.error` regardless - a single message can legitimately trigger multiple errors.
|
|
Loading…
Reference in New Issue
Block a user