@@ -15,6 +15,7 @@ use super::boundedness::{Bounded, Boundedness, Unbounded};
1515use super :: keyed_stream:: KeyedStream ;
1616use super :: optional:: Optional ;
1717use super :: singleton:: Singleton ;
18+ use super :: keyed_singleton:: KeyedSingleton ;
1819use crate :: compile:: ir:: { HydroIrOpMetadata , HydroNode , HydroRoot , TeeNode } ;
1920#[ cfg( stageleft_runtime) ]
2021use crate :: forward_handle:: { CycleCollection , ReceiverComplete } ;
@@ -1783,6 +1784,54 @@ where
17831784 } ,
17841785 )
17851786 }
1787+
1788+ /// Creates a [`KeyedStream`] with the same set of keys as `keys`, but with the elements in
1789+ /// `self` used as the values for *each* key.
1790+ ///
1791+ /// This is helpful when "broadcasting" a set of values so that all the keys have the same
1792+ /// values. For example, it can be used to send the same set of elements to several cluster
1793+ /// members, if the membership information is available as a [`KeyedSingleton`].
1794+ ///
1795+ /// # Example
1796+ /// ```rust
1797+ /// # use hydro_lang::prelude::*;
1798+ /// # use futures::StreamExt;
1799+ /// # tokio_test::block_on(hydro_lang::test_util::stream_transform_test(|process| {
1800+ /// # let tick = process.tick();
1801+ /// let keyed_singleton = // { 1: (), 2: () }
1802+ /// # process
1803+ /// # .source_iter(q!(vec![(1, ()), (2, ())]))
1804+ /// # .into_keyed()
1805+ /// # .batch(&tick, nondet!(/** test */))
1806+ /// # .first();
1807+ /// let stream = // [ "a", "b" ]
1808+ /// # process
1809+ /// # .source_iter(q!(vec!["a".to_string(), "b".to_string()]))
1810+ /// # .batch(&tick, nondet!(/** test */));
1811+ /// stream.repeat_with_keys(keyed_singleton)
1812+ /// # .entries().all_ticks()
1813+ /// # }, |mut stream| async move {
1814+ /// // { 1: ["a", "b" ], 2: ["a", "b"] }
1815+ /// # let mut results = Vec::new();
1816+ /// # for _ in 0..4 {
1817+ /// # results.push(stream.next().await.unwrap());
1818+ /// # }
1819+ /// # results.sort();
1820+ /// # assert_eq!(results, vec![(1, "a".to_string()), (1, "b".to_string()), (2, "a".to_string()), (2, "b".to_string())]);
1821+ /// # }));
1822+ /// ```
1823+ pub fn repeat_with_keys < K , V2 > (
1824+ self ,
1825+ keys : KeyedSingleton < K , V2 , L , Bounded > ,
1826+ ) -> KeyedStream < K , T , L , Bounded , O , R >
1827+ where
1828+ K : Clone ,
1829+ T : Clone ,
1830+ {
1831+ keys. keys ( ) . weaken_retries ( ) . cross_product_nested_loop ( self ) . into_keyed ( ) . assume_ordering (
1832+ nondet ! ( /** keyed stream does not depend on ordering of keys, cross_product_nested_loop preserves order of values */ )
1833+ )
1834+ }
17861835}
17871836
17881837impl < ' a , K , V1 , L , B : Boundedness , O : Ordering , R : Retries > Stream < ( K , V1 ) , L , B , O , R >
0 commit comments