Skip to content

Commit 63832f2

Browse files
committed
docs
Signed-off-by: Teo Koon Peng <[email protected]>
1 parent e3e1fb7 commit 63832f2

File tree

2 files changed

+23
-9
lines changed

2 files changed

+23
-9
lines changed

src/diagram.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use bevy_ecs::system::Commands;
1313
use fork_clone::ForkCloneOp;
1414
use fork_result::ForkResultOp;
1515
use join::JoinOp;
16+
pub use join::JoinOutput;
1617
pub use node_registry::*;
1718
pub use serialization::*;
1819
pub use split_serialized::*;
@@ -162,6 +163,8 @@ pub enum DiagramOperation {
162163
ForkResult(ForkResultOp),
163164

164165
/// If the request is a list-like or map-like object, split it into multiple responses.
166+
/// Note that the split output is a tuple of `(KeyOrIndex, Value)`, nodes receiving a split
167+
/// output should have request of that type instead of just the value type.
165168
///
166169
/// # Examples
167170
/// ```

src/diagram/join.rs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ use std::any::TypeId;
22

33
use schemars::JsonSchema;
44
use serde::{Deserialize, Serialize};
5+
use smallvec::SmallVec;
56
use tracing::debug;
67

7-
use crate::{Builder, IterBufferable, Output};
8+
use crate::{Builder, IterBufferable};
89

910
use super::{DiagramError, DynOutput, NodeRegistry, SerializeMessage};
1011

@@ -40,18 +41,22 @@ where
4041
debug!("join outputs {:?}", outputs);
4142

4243
if outputs.is_empty() {
43-
// do a empty join
44-
return Ok(([] as [Output<()>; 0])
45-
.join_vec::<4>(builder)
46-
.output()
47-
.into());
44+
// do a empty join, in practice, this branch is never ran because [`WorkflowBuilder`]
45+
// should error out if there is an empty join.
46+
return Err(DiagramError::EmptyJoin);
4847
}
4948

5049
let first_type = outputs[0].type_id;
5150

5251
let outputs = outputs
5352
.into_iter()
5453
.map(|o| {
54+
// joins is only supported for outputs of the same type. This is because joins of
55+
// different types produces a tuple and we cannot output a tuple as we don't
56+
// know the number and order of join inputs at compile time.
57+
// A workaround is to serialize them all the `serde_json::Value` or convert them to `Box<dyn Any>`.
58+
// But the problem with `Box<dyn Any>` is that we can't convert it back to the original type,
59+
// so nodes need to take a request of `JoinOutput<Box<dyn Any>>`.
5560
if o.type_id != first_type {
5661
Err(DiagramError::TypeMismatch)
5762
} else {
@@ -61,15 +66,21 @@ where
6166
.collect::<Result<Vec<_>, _>>()?;
6267

6368
// we don't know the number of items at compile time, so we just use a sensible number.
69+
// NOTE: Be sure to update `JoinOutput` if this changes.
6470
Ok(outputs.join_vec::<4>(builder).output().into())
6571
}
6672

73+
/// The resulting type of a `join` operation. Nodes receiving a join output must have request
74+
/// of this type. Note that the join output is NOT serializable. If you would like to serialize it,
75+
/// convert it to a `Vec` first.
76+
pub type JoinOutput<T> = SmallVec<[T; 4]>;
77+
6778
#[cfg(test)]
6879
mod tests {
6980
use serde_json::json;
70-
use smallvec::SmallVec;
7181
use test_log::test;
7282

83+
use super::*;
7384
use crate::{diagram::testing::DiagramTestFixture, Diagram, DiagramError, JsonPosition};
7485

7586
#[test]
@@ -86,8 +97,8 @@ mod tests {
8697
|builder, _config: ()| builder.create_map_block(get_split_value),
8798
);
8899

89-
fn serialize_join_output(small_vec: SmallVec<[i64; 4]>) -> serde_json::Value {
90-
serde_json::to_value(small_vec).unwrap()
100+
fn serialize_join_output(join_output: JoinOutput<i64>) -> serde_json::Value {
101+
serde_json::to_value(join_output).unwrap()
91102
}
92103

93104
fixture

0 commit comments

Comments
 (0)