feat: tedge flows, a configurable mapper using JavaScript#3650
feat: tedge flows, a configurable mapper using JavaScript#3650didier-wenzek merged 72 commits intothin-edge:mainfrom
Conversation
|
The javascript examples have to be updated. For instance the syntax |
Though it seems that Optional Chaining is part of ES2020 (which means it should be supported by QuickJS, I confirmed on the WASM version of QuickJS at least), so that would be the most similar to your previous syntax (just adding a For example: |
albinsuresh
left a comment
There was a problem hiding this comment.
Here is my first round of review comments focussing purely on the pipeline APIs and not much of the rust infra code. Unfortunately, I'm having some trouble testing the feature due to some certificate misconfiguration preventing the mapper from even starting with the following error:
Jun 10 06:36:23 2a9636a9acc5 tedge-mapper[3107]: 2025-06-10T06:36:23.630655575Z ERROR Runtime: Actor MQTT-2 has finished unsuccessfully: ActorError(InvalidPrivateKey(InvalidCertificate(Other(OtherError(UnsupportedCertVersion)))))
Will provide additional usability feedback once that issue is resolved.
| stages = [ | ||
| { filter = "add_timestamp.js" }, | ||
| { filter = "drop_stragglers.js", config = { max_delay = 60 } }, | ||
| { filter = "te_to_c8y.js", meta_topics = ["te/+/+/+/+/m/+/meta"] } |
There was a problem hiding this comment.
Wondering if stage-wise meta_topics is really necessary or a pipe-line level meta_topics would be sufficient (and simpler to maintain).
There was a problem hiding this comment.
What we want here is for the messages received on the meta topics to be directly delivered to the stage. The other stages have no way to do something meaningful with these messages (In this case, units for various measurement types).
A better name might be config_topics.
| stages = [ | ||
| { filter = "add_timestamp.js" }, | ||
| { filter = "drop_stragglers.js", config = { max_delay = 60 } }, | ||
| { filter = "te_to_c8y.js", meta_topics = ["te/+/+/+/+/m/+/meta"] } |
There was a problem hiding this comment.
Expressing the correlation between the input_topic and meta_topic with wildcards appears slightly inaccurate/misleading. For example, when the above definition is applied on a te/+/+/+/+/m/temperature measurement, the corresponding meta_topic should have only been te/+/+/+/+/m/temperature/meta. But with the wildcard te/+/+/+/+/m/+/meta subscription, it covers the meta topics of other measurements like m/pressure/meta, m/humidity/meta etc as well. Wondering if we should introduce some sort of variable substitution syntax like m/{m_type} and m/{m_type}/meta so that this correlation is better expressed.
There was a problem hiding this comment.
What you propose seems too specific to this specific example (adding units to measurements leveraging the meta topics as defined by thin-edge). Sure the script (here te_to_c8y.js) has to appropriately match data and meta data, but why should the generic mapper enforce that from the outside?
Though I couldn't fix the cert issue, I've moved on by completely disabling auth settings. |
|
|
||
| stages = [ | ||
| { filter = "add_timestamp.js" }, | ||
| { filter = "circuit-breaker.js", tick_every_seconds = 1, config = { stats_topic = "te/error", too_many = 10000, message_on_too_many = { topic = "te/device/main///a/too-many-messages", payload = "too many messages" }, message_on_back_to_normal = { topic = "te/device/main///a/too-many-messages", payload = "back to normal" } } } |
There was a problem hiding this comment.
This line highlights pain points with the current configuration format.
- There are two levels of config which is confusing.
tick_every_secondis used by the engine, whileconfig.too_manyis passed to the script. Flattening theconfigmight be simpler. - TOML inline tables are intended to appear on a single line. Leading to painfully long lines as here.
- Passing a JSON payload to the filter config is not straightforward. Currently the engine expects a string and the JS filter has to stringyfy the payload.
fba7bdd to
2e41d5e
Compare
2e41d5e to
e759966
Compare
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
In some context `Flow script` is more appropriate. For instance, when two steps use the same script. Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
- process -> onMessage - tick -> onInterval - updateConfig -> OnConfigUpdate Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Add timestamp to message object Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: reubenmiller <reuben.d.miller@gmail.com>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
For now, the bindgen feature is enable for all targets. One could consider to use bindings shipped with quickjs when available. See https://github.com/delskayn/rquickjs?tab=readme-ov-file#supported-platforms Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
For now, the bindgen feature is enable for all targets. One could consider to use bindings shipped with quickjs when available. See https://github.com/delskayn/rquickjs?tab=readme-ov-file#supported-platforms Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
The goal is to be in position to add other types of inputs. Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: reubenmiller <reuben.d.miller@gmail.com>
Signed-off-by: reubenmiller <reuben.d.miller@gmail.com>
…ort compiling quickjs Signed-off-by: reubenmiller <reuben.d.miller@gmail.com>
Signed-off-by: reubenmiller <reuben.d.miller@gmail.com>
Signed-off-by: reubenmiller <reuben.d.miller@gmail.com>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
The type has also been changed, from a number of seconds to a human time duration. Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
error: hiding a lifetime that's elided elsewhere is confusing Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Proposed changes
A first step toward configurable mappers that users can extend and adapt to their use-cases
with their own filtering and message transformation rules.
The following steps are described here: #3756
Features:
MQTT sub| step-1 |step-2 | ... | step-n | MQTT pubCombine user-provided JS filters with built-in Rust filtersCriteria:
Examples:
Types of changes
Paste Link to the issue
#3756
Checklist
just prepare-devonce)just formatas mentioned in CODING_GUIDELINESjust checkas mentioned in CODING_GUIDELINESFurther comments
This PR uses quickJS as an alternative to: