Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(descriptors): make operators section optional #193

Merged
merged 1 commit into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 56 additions & 5 deletions zenoh-flow-descriptors/src/dataflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,16 @@ use zenoh_flow_commons::{Configuration, NodeId, RuntimeId};
///
/// In Zenoh-Flow, we divide a descriptor into sections, each responsible for a single aspect of the applications.
///
/// The **required** sections are:
/// The *main* sections are:
/// - `name` : A short human-readable summary of what your data flow will do.
/// - `sources` : A non-empty list of Source(s) to feed data into your data flow.
/// - `operators`: A list of Operator(s) to perform transformation on the data.
/// - `operators`: A list of Operator(s) to perform transformation on the data. A data flow can have no Operator, in
/// which case this section can be omitted.
/// - `sinks` : A non-empty list of Sink(s) to output the result of the transformation(s) performed in your data
/// flow.
/// - `links` : How the different nodes of your data flow are connected.
///
/// Special, **optional**, sections can also be added to tweak a data flow:
/// Special, *optional*, sections can also be added to tweak a data flow:
/// - `uuid`: The unique identifier to give to an instance of this data flow.
/// If not provided, Zenoh-Flow will generate a random one when instantiating the flow.
///
Expand All @@ -71,13 +72,13 @@ use zenoh_flow_commons::{Configuration, NodeId, RuntimeId};
///
/// The three types of nodes -- Sources, Sinks and Operators -- share a similar structure.
///
/// The **required** sections are:
/// The *required* sections are:
/// - `id` : A unique name -- within your data flow.
/// - `library`: A [Url](url::Url) pointing at the implementation of the node's logic.
/// - `inputs` : The entry points of the node (i.e. to receive data). ⚠️ Only for **Sinks** and **Operators**.
/// - `outputs`: The exit points of the node (i.e. to forward data). ⚠️ Only for **Sources** and **Operators**.
///
/// The **optional** sections are:
/// The *optional* sections are:
/// - `description` : A human-readable description of what the node does.
/// - `configuration`: To pass down values to the node when Zenoh-Flow creates it. Values in a node's section will
/// *overwrite* that of the data flow.
Expand Down Expand Up @@ -248,6 +249,7 @@ pub struct DataFlowDescriptor {
#[serde(default)]
pub(crate) configuration: Configuration,
/// *(optional)* A list of Operator(s), the nodes that manipulate and / or produce data.
#[serde(default)]
pub(crate) operators: Vec<OperatorDescriptor>,
/// A non-empty list of Source(s), the nodes that provide data to the data flow.
pub(crate) sources: Vec<SourceDescriptor>,
Expand Down Expand Up @@ -333,6 +335,55 @@ mod tests {
}
]
}
"#;
let data_flow_json = serde_json::from_str::<DataFlowDescriptor>(flow_json_str)
.expect("Failed to deserialize flow from JSON");
assert!(serde_json::to_string(&data_flow_json).is_ok());
}

#[test]
fn test_serialization_deserialization_no_operators() {
let flow_json_str = r#"
{
"name": "DataFlow",

"configuration": {
"foo": "bar"
},

"sources": [
{
"id": "Source",
"descriptor": "file:///home/zenoh-flow/nodes/source.yaml",
"configuration": {
"answer": 0
}
}
],

"sinks": [
{
"id": "Sink",
"descriptor": "file:///home/zenoh-flow/nodes/sink.yaml",
"configuration": {
"answer": 2
}
}
],

"links": [
{
"from": {
"node": "Source",
"output": "o-source"
},
"to": {
"node": "Sink",
"input": "i-sink"
}
}
]
}
"#;
let data_flow_json = serde_json::from_str::<DataFlowDescriptor>(flow_json_str)
.expect("Failed to deserialize flow from JSON");
Expand Down
1 change: 1 addition & 0 deletions zenoh-flow-descriptors/src/flattened/dataflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ pub struct FlattenedDataFlowDescriptor {
/// A non-empty list of Sources.
pub sources: Vec<FlattenedSourceDescriptor>,
/// A list of Operators.
#[serde(default)]
pub operators: Vec<FlattenedOperatorDescriptor>,
/// A non-empty list of Sinks.
pub sinks: Vec<FlattenedSinkDescriptor>,
Expand Down
47 changes: 47 additions & 0 deletions zenoh-flow-descriptors/src/flattened/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,3 +425,50 @@ links:
assert!(flat_flow_json.uuid.is_none());
assert!(flat_flow_yaml.mapping.is_empty());
}

#[test]
fn test_serialize_deserialize_no_operators() {
let flow_yaml = r#"
name: test-flow

sources:
- id: source-0
description: source-0
library: "file:///home/zenoh-flow/libsource.so"
outputs:
- out-1
configuration:
id: source-0

sinks:
- id: sink-2
description: sink-2
library: "file:///home/zenoh-flow/libsink.so"
inputs:
- in-1
configuration:
id: sink-2

links:
- from:
node: source-0
output: out-1
to:
node: sink-2
input: in-1
"#;

let flat_flow_yaml = serde_yaml::from_str::<FlattenedDataFlowDescriptor>(flow_yaml)
.expect("Failed to deserialize flow from YAML");

let json_string_flow =
serde_json::to_string(&flat_flow_yaml).expect("Failed to serialize flow as JSON");

let flat_flow_json =
serde_json::from_str::<FlattenedDataFlowDescriptor>(json_string_flow.as_str())
.expect("Failed to deserialize flow from JSON");

assert_eq!(flat_flow_yaml, flat_flow_json);
assert!(flat_flow_json.uuid.is_none());
assert!(flat_flow_yaml.mapping.is_empty());
}
Loading