Pulse id diff in events endpoint via transform chain
This commit is contained in:
@@ -1,13 +1,12 @@
|
||||
use crate::collect::Collect;
|
||||
use crate::rangefilter2::RangeFilter2;
|
||||
use crate::tcprawclient::open_tcp_streams;
|
||||
use crate::transform::build_merged_event_transform;
|
||||
use crate::transform::EventsToTimeBinnable;
|
||||
use crate::transform::TimeBinnableToCollectable;
|
||||
use err::Error;
|
||||
use futures_util::stream;
|
||||
use futures_util::StreamExt;
|
||||
use items_0::on_sitemty_data;
|
||||
use items_0::streamitem::sitem_data;
|
||||
use items_0::Events;
|
||||
use items_2::channelevents::ChannelEvents;
|
||||
use items_2::merger::Merger;
|
||||
use items_2::streams::PlainEventStream;
|
||||
@@ -18,96 +17,44 @@ use query::api4::events::PlainEventsQuery;
|
||||
use serde_json::Value as JsonValue;
|
||||
use std::time::Instant;
|
||||
|
||||
pub async fn plain_events_json(evq: &PlainEventsQuery, chconf: &ChConf, cluster: &Cluster) -> Result<JsonValue, Error> {
|
||||
if evq.channel().name() == "wasm-test-01" {
|
||||
use wasmer::Value;
|
||||
let wasm = evq.channel().name().as_bytes();
|
||||
let mut store = wasmer::Store::default();
|
||||
let module = wasmer::Module::new(&store, wasm).unwrap();
|
||||
let import_object = wasmer::imports! {};
|
||||
let instance = wasmer::Instance::new(&mut store, &module, &import_object).unwrap();
|
||||
let add_one = instance.exports.get_function("event_transform").unwrap();
|
||||
let result = add_one.call(&mut store, &[Value::I32(42)]).unwrap();
|
||||
assert_eq!(result[0], Value::I32(43));
|
||||
}
|
||||
pub async fn plain_events_json(
|
||||
evq: &PlainEventsQuery,
|
||||
_chconf: &ChConf,
|
||||
cluster: &Cluster,
|
||||
) -> Result<JsonValue, Error> {
|
||||
info!("plain_events_json evquery {:?}", evq);
|
||||
// TODO remove magic constant
|
||||
let deadline = Instant::now() + evq.timeout();
|
||||
let events_max = evq.events_max();
|
||||
let evquery = evq.clone();
|
||||
info!("plain_events_json evquery {:?}", evquery);
|
||||
//let ev_agg_kind = evquery.agg_kind().as_ref().map_or(AggKind::Plain, |x| x.clone());
|
||||
//info!("plain_events_json ev_agg_kind {:?}", ev_agg_kind);
|
||||
warn!("TODO feed through transform chain");
|
||||
let empty = if evq.transform().is_pulse_id_diff() {
|
||||
use items_0::Empty;
|
||||
Box::new(items_2::eventsdim0::EventsDim0::<i64>::empty())
|
||||
} else {
|
||||
items_2::empty::empty_events_dyn_ev(&chconf.scalar_type, &chconf.shape)?
|
||||
};
|
||||
info!("plain_events_json with empty item {}", empty.type_name());
|
||||
let empty = ChannelEvents::Events(empty);
|
||||
let empty = sitem_data(empty);
|
||||
// TODO should be able to ask for data-events only, instead of mixed data and status events.
|
||||
let inps = open_tcp_streams::<_, items_2::channelevents::ChannelEvents>(&evquery, cluster).await?;
|
||||
//let inps = open_tcp_streams::<_, Box<dyn items_2::Events>>(&query, cluster).await?;
|
||||
// TODO propagate also the max-buf-len for the first stage event reader:
|
||||
let stream = Merger::new(inps, 1024);
|
||||
|
||||
// Transforms that keep state between batches of events, usually only useful after merge.
|
||||
// Example: pulse-id-diff
|
||||
use futures_util::Stream;
|
||||
use items_0::streamitem::Sitemty;
|
||||
use std::pin::Pin;
|
||||
let stream: Pin<Box<dyn Stream<Item = Sitemty<ChannelEvents>> + Send>> = if evq.transform().is_pulse_id_diff() {
|
||||
let mut pulse_last = None;
|
||||
Box::pin(stream.map(move |item| {
|
||||
on_sitemty_data!(item, |item| {
|
||||
use items_0::streamitem::RangeCompletableItem;
|
||||
use items_0::streamitem::StreamItem;
|
||||
use items_0::Appendable;
|
||||
use items_0::Empty;
|
||||
let x = match item {
|
||||
ChannelEvents::Events(item) => {
|
||||
let (tss, pulses) = items_0::EventsNonObj::into_tss_pulses(item);
|
||||
let mut item = items_2::eventsdim0::EventsDim0::empty();
|
||||
for (ts, pulse) in tss.into_iter().zip(pulses) {
|
||||
let value = if let Some(last) = pulse_last {
|
||||
pulse as i64 - last as i64
|
||||
} else {
|
||||
0
|
||||
};
|
||||
item.push(ts, pulse, value);
|
||||
pulse_last = Some(pulse);
|
||||
}
|
||||
ChannelEvents::Events(Box::new(item))
|
||||
}
|
||||
ChannelEvents::Status(x) => ChannelEvents::Status(x),
|
||||
};
|
||||
Ok(StreamItem::DataItem(RangeCompletableItem::Data(x)))
|
||||
})
|
||||
}))
|
||||
} else {
|
||||
Box::pin(stream)
|
||||
};
|
||||
|
||||
let mut tr = build_merged_event_transform(evq.transform())?;
|
||||
// TODO make sure the empty container arrives over the network.
|
||||
let inps = open_tcp_streams::<_, ChannelEvents>(&evq, cluster).await?;
|
||||
// TODO propagate also the max-buf-len for the first stage event reader.
|
||||
// TODO use a mixture of count and byte-size as threshold.
|
||||
let stream = Merger::new(inps, evq.merger_out_len_max());
|
||||
#[cfg(DISABLED)]
|
||||
let stream = stream.map(|item| {
|
||||
info!("item after merge: {item:?}");
|
||||
item
|
||||
});
|
||||
//let stream = RangeFilter2::new(stream, evq.range().try_into()?, evquery.one_before_range());
|
||||
#[cfg(DISABLED)]
|
||||
let stream = crate::rangefilter2::RangeFilter2::new(stream, evq.range().try_into()?, evquery.one_before_range());
|
||||
#[cfg(DISABLED)]
|
||||
let stream = stream.map(|item| {
|
||||
info!("item after rangefilter: {item:?}");
|
||||
item
|
||||
});
|
||||
let stream = stream::iter([empty]).chain(stream);
|
||||
let stream = stream.map(move |k| {
|
||||
on_sitemty_data!(k, |k| {
|
||||
let k: Box<dyn Events> = Box::new(k);
|
||||
info!("-------------------------\ngot len {}", k.len());
|
||||
let k = tr.0.transform(k);
|
||||
Ok(StreamItem::DataItem(RangeCompletableItem::Data(k)))
|
||||
})
|
||||
});
|
||||
let stream = PlainEventStream::new(stream);
|
||||
let stream = EventsToTimeBinnable::new(stream);
|
||||
let stream = TimeBinnableToCollectable::new(stream);
|
||||
let collected = Collect::new(stream, deadline, events_max, Some(evq.range().clone()), None).await;
|
||||
|
||||
//let collected = crate::collect::collect(stream, deadline, events_max, Some(evq.range().clone()), None).await?;
|
||||
let collected = Collect::new(stream, deadline, evq.events_max(), Some(evq.range().clone()), None).await?;
|
||||
let jsval = serde_json::to_value(&collected)?;
|
||||
Ok(jsval)
|
||||
}
|
||||
|
||||
@@ -1,17 +1,26 @@
|
||||
use crate::collect::Collect;
|
||||
use crate::test::runfut;
|
||||
use crate::transform::build_event_transform;
|
||||
use crate::transform::build_time_binning_transform;
|
||||
use crate::transform::EventsToTimeBinnable;
|
||||
use crate::transform::TimeBinnableToCollectable;
|
||||
use err::Error;
|
||||
use futures_util::stream;
|
||||
use futures_util::StreamExt;
|
||||
use items_0::on_sitemty_data;
|
||||
use items_0::streamitem::sitem_data;
|
||||
use items_0::streamitem::RangeCompletableItem;
|
||||
use items_0::streamitem::StreamItem;
|
||||
use items_0::transform::EventStreamBox;
|
||||
use items_0::transform::EventStreamTrait;
|
||||
use items_0::WithLen;
|
||||
use items_2::eventsdim0::EventsDim0CollectorOutput;
|
||||
use items_2::streams::PlainEventStream;
|
||||
use items_2::testgen::make_some_boxed_d0_f32;
|
||||
use netpod::log::*;
|
||||
use netpod::timeunits::SEC;
|
||||
use netpod::FromUrl;
|
||||
use query::transform::TransformQuery;
|
||||
use std::time::Duration;
|
||||
use std::time::Instant;
|
||||
|
||||
@@ -69,3 +78,42 @@ fn collect_channel_events_01() -> Result<(), Error> {
|
||||
};
|
||||
runfut(fut)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn collect_channel_events_pulse_id_diff() -> Result<(), Error> {
|
||||
let fut = async {
|
||||
let trqu = TransformQuery::from_url(&"https://data-api.psi.ch/?binningScheme=pulseIdDiff".parse()?)?;
|
||||
info!("{trqu:?}");
|
||||
let evs0 = make_some_boxed_d0_f32(20, SEC * 10, SEC * 1, 0, 28736487);
|
||||
let evs1 = make_some_boxed_d0_f32(20, SEC * 30, SEC * 1, 0, 882716583);
|
||||
let stream = stream::iter(vec![
|
||||
sitem_data(evs0),
|
||||
sitem_data(evs1),
|
||||
Ok(StreamItem::DataItem(RangeCompletableItem::RangeComplete)),
|
||||
]);
|
||||
let mut tr = build_event_transform(&trqu)?;
|
||||
let stream = stream.map(move |x| {
|
||||
on_sitemty_data!(x, |x| {
|
||||
let x = tr.0.transform(x);
|
||||
Ok(StreamItem::DataItem(RangeCompletableItem::Data(x)))
|
||||
})
|
||||
});
|
||||
let stream = PlainEventStream::new(stream);
|
||||
let stream = EventsToTimeBinnable::new(stream);
|
||||
let deadline = Instant::now() + Duration::from_millis(4000);
|
||||
let events_max = 10000;
|
||||
let stream = Box::pin(stream);
|
||||
let stream = build_time_binning_transform(&trqu, stream)?;
|
||||
let stream = TimeBinnableToCollectable::new(stream);
|
||||
let res = Collect::new(stream, deadline, events_max, None, None).await?;
|
||||
if let Some(res) = res.as_any_ref().downcast_ref::<EventsDim0CollectorOutput<i64>>() {
|
||||
eprintln!("Great, a match");
|
||||
eprintln!("{res:?}");
|
||||
assert_eq!(res.len(), 40);
|
||||
} else {
|
||||
return Err(Error::with_msg(format!("bad type of collected result")));
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
runfut(fut)
|
||||
}
|
||||
|
||||
@@ -256,6 +256,7 @@ fn transform_chain_correctness_01() -> Result<(), Error> {
|
||||
type STY = f32;
|
||||
let tq = TransformQuery::default_time_binned();
|
||||
let empty = EventsDim0::<STY>::empty();
|
||||
build_event_transform(&tq, empty.into())?;
|
||||
build_event_transform(&tq)?;
|
||||
todo!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ where
|
||||
do_time_weight: bool,
|
||||
deadline: Instant,
|
||||
deadline_fut: Pin<Box<dyn Future<Output = ()> + Send>>,
|
||||
range_complete: bool,
|
||||
range_final: bool,
|
||||
binner: Option<<T as TimeBinnableTy>::TimeBinner>,
|
||||
done_data: bool,
|
||||
done: bool,
|
||||
@@ -65,7 +65,7 @@ where
|
||||
fmt.debug_struct(any::type_name::<Self>())
|
||||
.field("range", &self.range)
|
||||
.field("deadline", &self.deadline)
|
||||
.field("range_complete", &self.range_complete)
|
||||
.field("range_final", &self.range_final)
|
||||
.field("binner", &self.binner)
|
||||
.finish()
|
||||
}
|
||||
@@ -84,7 +84,7 @@ where
|
||||
do_time_weight,
|
||||
deadline,
|
||||
deadline_fut,
|
||||
range_complete: false,
|
||||
range_final: false,
|
||||
binner: None,
|
||||
done_data: false,
|
||||
done: false,
|
||||
@@ -123,7 +123,7 @@ where
|
||||
Ready(None)
|
||||
} else if self.done_data {
|
||||
self.done = true;
|
||||
if self.range_complete {
|
||||
if self.range_final {
|
||||
Ready(Some(Ok(StreamItem::DataItem(RangeCompletableItem::RangeComplete))))
|
||||
} else {
|
||||
continue;
|
||||
@@ -132,7 +132,7 @@ where
|
||||
match self.deadline_fut.poll_unpin(cx) {
|
||||
Ready(()) => {
|
||||
trace2!("timeout");
|
||||
let self_range_complete = self.range_complete;
|
||||
let self_range_complete = self.range_final;
|
||||
if let Some(binner) = self.binner.as_mut() {
|
||||
trace2!("bins ready count before finish {}", binner.bins_ready_count());
|
||||
// TODO rework the finish logic
|
||||
@@ -159,7 +159,7 @@ where
|
||||
StreamItem::DataItem(item) => match item {
|
||||
RangeCompletableItem::RangeComplete => {
|
||||
debug!("see RangeComplete");
|
||||
self.range_complete = true;
|
||||
self.range_final = true;
|
||||
continue;
|
||||
}
|
||||
RangeCompletableItem::Data(item) => {
|
||||
@@ -193,7 +193,7 @@ where
|
||||
},
|
||||
Ready(None) => {
|
||||
trace!("finish up");
|
||||
let self_range_complete = self.range_complete;
|
||||
let self_range_complete = self.range_final;
|
||||
if let Some(binner) = self.binner.as_mut() {
|
||||
trace!("bins ready count before finish {}", binner.bins_ready_count());
|
||||
// TODO rework the finish logic
|
||||
|
||||
@@ -32,8 +32,6 @@ pub async fn timebinned_json(query: &BinnedQuery, chconf: &ChConf, cluster: &Clu
|
||||
//crate::transform::build_event_transform(tr, inp);
|
||||
query.transform();
|
||||
|
||||
crate::transform::build_event_transform;
|
||||
|
||||
// TODO
|
||||
let evquery = PlainEventsQuery::new(query.channel().clone(), query.range().clone()).for_time_weighted_scalar();
|
||||
let inps = open_tcp_streams::<_, items_2::channelevents::ChannelEvents>(&evquery, cluster).await?;
|
||||
|
||||
@@ -10,6 +10,7 @@ use items_0::transform::CollectableStreamBox;
|
||||
use items_0::transform::CollectableStreamTrait;
|
||||
use items_0::transform::EventStreamBox;
|
||||
use items_0::transform::EventStreamTrait;
|
||||
use items_0::transform::TimeBinnableStreamBox;
|
||||
use items_0::transform::TimeBinnableStreamTrait;
|
||||
use items_0::transform::TransformEvent;
|
||||
use items_0::transform::TransformProperties;
|
||||
@@ -24,7 +25,7 @@ use std::pin::Pin;
|
||||
use std::task::Context;
|
||||
use std::task::Poll;
|
||||
|
||||
pub fn build_event_transform(tr: &TransformQuery, inp: EventStreamBox) -> Result<TransformEvent, Error> {
|
||||
pub fn build_event_transform(tr: &TransformQuery) -> Result<TransformEvent, Error> {
|
||||
let trev = tr.get_tr_event();
|
||||
match trev {
|
||||
EventTransformQuery::ValueFull => Ok(make_transform_identity()),
|
||||
@@ -42,6 +43,14 @@ pub fn build_event_transform(tr: &TransformQuery, inp: EventStreamBox) -> Result
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_merged_event_transform(tr: &TransformQuery) -> Result<TransformEvent, Error> {
|
||||
let trev = tr.get_tr_event();
|
||||
match trev {
|
||||
EventTransformQuery::PulseIdDiff => Ok(make_transform_pulse_id_diff()),
|
||||
_ => Ok(make_transform_identity()),
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EventsToTimeBinnable {
|
||||
inp: Pin<Box<dyn EventStreamTrait>>,
|
||||
}
|
||||
@@ -133,22 +142,16 @@ impl CollectableStreamTrait for TimeBinnableToCollectable {}
|
||||
pub fn build_time_binning_transform(
|
||||
tr: &TransformQuery,
|
||||
inp: Pin<Box<dyn TimeBinnableStreamTrait>>,
|
||||
) -> Result<TransformEvent, Error> {
|
||||
let trev = tr.get_tr_event();
|
||||
match trev {
|
||||
EventTransformQuery::ValueFull => Ok(make_transform_identity()),
|
||||
EventTransformQuery::MinMaxAvgDev => Ok(make_transform_min_max_avg()),
|
||||
EventTransformQuery::ArrayPick(..) => Err(Error::with_msg_no_trace(format!(
|
||||
"build_event_transform don't know what to do {trev:?}"
|
||||
))),
|
||||
EventTransformQuery::PulseIdDiff => Ok(make_transform_pulse_id_diff()),
|
||||
EventTransformQuery::EventBlobsVerbatim => Err(Error::with_msg_no_trace(format!(
|
||||
"build_event_transform don't know what to do {trev:?}"
|
||||
))),
|
||||
EventTransformQuery::EventBlobsUncompressed => Err(Error::with_msg_no_trace(format!(
|
||||
"build_event_transform don't know what to do {trev:?}"
|
||||
))),
|
||||
}
|
||||
) -> Result<TimeBinnableStreamBox, Error> {
|
||||
let trev = tr.get_tr_time_binning();
|
||||
let res = match trev {
|
||||
TimeBinningTransformQuery::None => TimeBinnableStreamBox(inp),
|
||||
_ => {
|
||||
// TODO apply the desired transformations.
|
||||
todo!()
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn build_full_transform_collectable(
|
||||
|
||||
Reference in New Issue
Block a user