use crate::channelevents::ChannelEvents; use crate::empty::empty_events_dyn_ev; use crate::ChannelEventsInput; use crate::Error; use futures_util::Future; use futures_util::Stream; use futures_util::StreamExt; use items_0::collect_s::Collected; use items_0::collect_s::Collector; use items_0::collect_s::ToJsonResult; use items_0::streamitem::RangeCompletableItem; use items_0::streamitem::Sitemty; use items_0::streamitem::StreamItem; use items_0::timebin::TimeBinnable; use items_0::timebin::TimeBinner; use items_0::transform::EventTransform; use netpod::log::*; use netpod::BinnedRange; use netpod::BinnedRangeEnum; use netpod::ScalarType; use netpod::Shape; use std::pin::Pin; use std::task::Context; use std::task::Poll; use std::time::Duration; use std::time::Instant; fn flush_binned( binner: &mut Box, coll: &mut Option>, force: bool, ) -> Result<(), Error> { trace!("flush_binned bins_ready_count: {}", binner.bins_ready_count()); if force { if binner.bins_ready_count() == 0 { debug!("cycle the binner forced"); binner.cycle(); } else { debug!("bins ready, do not force"); } } if binner.bins_ready_count() > 0 { let ready = binner.bins_ready(); match ready { Some(mut ready) => { trace!("binned_collected ready {ready:?}"); if coll.is_none() { *coll = Some(ready.as_collectable_mut().new_collector()); } let cl = coll.as_mut().unwrap(); cl.ingest(ready.as_collectable_mut()); Ok(()) } None => Err(format!("bins_ready_count but no result").into()), } } else { Ok(()) } } #[derive(Debug)] pub struct BinnedCollectedResult { pub range_final: bool, pub did_timeout: bool, pub result: Box, } fn _old_binned_collected( scalar_type: ScalarType, shape: Shape, binrange: BinnedRangeEnum, transformer: &dyn EventTransform, deadline: Instant, inp: Pin> + Send>>, ) -> Result { event!(Level::TRACE, "binned_collected"); let transprops = transformer.query_transform_properties(); // TODO use a trait to allow check of unfinished data [hcn2956jxhwsf] // TODO implement continue-at [hcn2956jxhwsf] // TODO maybe TimeBinner should take all ChannelEvents and handle this? let empty_item = empty_events_dyn_ev(&scalar_type, &shape)?; let tmp_item = Ok(StreamItem::DataItem(RangeCompletableItem::Data(ChannelEvents::Events( empty_item, )))); let empty_stream = futures_util::stream::once(futures_util::future::ready(tmp_item)); let mut stream = empty_stream.chain(inp); todo!() } enum BinnedCollectedState { Init, Run, Done, } pub struct BinnedCollected { state: BinnedCollectedState, binrange: BinnedRangeEnum, scalar_type: ScalarType, shape: Shape, do_time_weight: bool, did_timeout: bool, range_final: bool, coll: Option>, binner: Option>, inp: Pin>, } impl BinnedCollected { const fn self_name() -> &'static str { "BinnedCollected" } pub fn new( binrange: BinnedRangeEnum, scalar_type: ScalarType, shape: Shape, do_time_weight: bool, //transformer: &dyn Transformer, deadline: Instant, inp: Pin>, ) -> Self { Self { state: BinnedCollectedState::Init, binrange, scalar_type, shape, do_time_weight, did_timeout: false, range_final: false, coll: None, binner: None, inp, } } fn handle_item(&mut self, item: StreamItem>) -> Result<(), Error> { match item { StreamItem::DataItem(k) => match k { RangeCompletableItem::RangeComplete => { self.range_final = true; } RangeCompletableItem::Data(k) => match k { ChannelEvents::Events(events) => { if self.binner.is_none() { let bb = events .as_time_binnable() .time_binner_new(self.binrange.clone(), self.do_time_weight); self.binner = Some(bb); } let binner = self.binner.as_mut().unwrap(); trace!("handle_item call binner.ingest"); binner.ingest(events.as_time_binnable()); flush_binned(binner, &mut self.coll, false)?; } ChannelEvents::Status(item) => { trace!("{:?}", item); } }, }, StreamItem::Log(item) => { // TODO collect also errors here? trace!("{:?}", item); } StreamItem::Stats(item) => { // TODO do something with the stats trace!("{:?}", item); } } Ok(()) } fn result(&mut self) -> Result { if let Some(mut binner) = self.binner.take() { if self.range_final { trace!("range_final"); binner.set_range_complete(); } else { debug!("not range_final"); } if self.did_timeout { warn!("did_timeout"); } else { trace!("not did_timeout"); binner.cycle(); } flush_binned(&mut binner, &mut self.coll, false)?; if self.coll.is_none() { debug!("force a bin"); flush_binned(&mut binner, &mut self.coll, true)?; } else { trace!("coll is already some"); } } else { error!("no binner, should always have one"); } let result = match self.coll.take() { Some(mut coll) => { let res = coll .result(None, Some(self.binrange.clone())) .map_err(|e| format!("{e}"))?; res } None => { error!("binned_collected nothing collected"); return Err(Error::from(format!("binned_collected nothing collected"))); } }; let ret = BinnedCollectedResult { range_final: self.range_final, did_timeout: self.did_timeout, result, }; Ok(ret) } } impl Future for BinnedCollected { type Output = Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { let span = span!(Level::INFO, BinnedCollected::self_name()); let _spg = span.enter(); use Poll::*; loop { break match &self.state { BinnedCollectedState::Init => { self.state = BinnedCollectedState::Run; continue; } BinnedCollectedState::Run => match self.inp.poll_next_unpin(cx) { Ready(Some(Ok(item))) => match self.handle_item(item) { Ok(()) => continue, Err(e) => { self.state = BinnedCollectedState::Done; Ready(Err(e)) } }, Ready(Some(Err(e))) => { self.state = BinnedCollectedState::Done; Ready(Err(e.into())) } Ready(None) => { self.state = BinnedCollectedState::Done; Ready(self.result()) } Pending => Pending, }, BinnedCollectedState::Done => Ready(Err(Error::from(format!("already done")))), }; } } }