WIP on request by pulse id

This commit is contained in:
Dominik Werder
2023-03-07 16:26:56 +01:00
parent 7bb847b93e
commit 617c21cdc3
8 changed files with 530 additions and 475 deletions
+1 -1
View File
@@ -69,7 +69,7 @@ pub async fn get_binned(
}; };
let agg_kind = AggKind::DimXBins1; let agg_kind = AggKind::DimXBins1;
let range = NanoRange::from_date_time(beg_date, end_date); let range = NanoRange::from_date_time(beg_date, end_date);
let mut query = BinnedQuery::new(channel, range, bin_count, Some(agg_kind)); let mut query = BinnedQuery::new(channel, range, bin_count);
query.set_cache_usage(cache_usage); query.set_cache_usage(cache_usage);
query.set_disk_stats_every(ByteSize(1024 * disk_stats_every_kb)); query.set_disk_stats_every(ByteSize(1024 * disk_stats_every_kb));
let hp = HostPort { host: host, port: port }; let hp = HostPort { host: host, port: port };
+19 -81
View File
@@ -35,6 +35,7 @@ use items_0::TimeBinnable;
use items_0::TimeBinner; use items_0::TimeBinner;
use netpod::log::*; use netpod::log::*;
use netpod::timeunits::*; use netpod::timeunits::*;
use netpod::transform::Transform;
use netpod::AggKind; use netpod::AggKind;
use netpod::BinnedRange; use netpod::BinnedRange;
use netpod::NanoRange; use netpod::NanoRange;
@@ -225,11 +226,11 @@ pub trait TimeBinnableTypeAggregator: Send {
pub fn empty_events_dyn_ev( pub fn empty_events_dyn_ev(
scalar_type: &ScalarType, scalar_type: &ScalarType,
shape: &Shape, shape: &Shape,
agg_kind: &AggKind, transform: &Transform,
) -> Result<Box<dyn Events>, Error> { ) -> Result<Box<dyn Events>, Error> {
let ret: Box<dyn Events> = match shape { let ret: Box<dyn Events> = match shape {
Shape::Scalar => match agg_kind { Shape::Scalar => match transform {
AggKind::Plain | AggKind::TimeWeightedScalar => { _ if true => {
use ScalarType::*; use ScalarType::*;
type K<T> = eventsdim0::EventsDim0<T>; type K<T> = eventsdim0::EventsDim0<T>;
match scalar_type { match scalar_type {
@@ -247,14 +248,14 @@ pub fn empty_events_dyn_ev(
STRING => Box::new(K::<String>::empty()), STRING => Box::new(K::<String>::empty()),
} }
} }
AggKind::PulseIdDiff => Box::new(eventsdim0::EventsDim0::<i64>::empty()), _ if true => Box::new(eventsdim0::EventsDim0::<i64>::empty()),
AggKind::DimXBins1 | AggKind::DimXBinsN(..) | AggKind::EventBlobs => { _ => {
error!("TODO empty_events_dyn_ev {agg_kind:?} {scalar_type:?} {shape:?}"); error!("TODO empty_events_dyn_ev {transform:?} {scalar_type:?} {shape:?}");
err::todoval() err::todoval()
} }
}, },
Shape::Wave(..) => match agg_kind { Shape::Wave(..) => match transform {
AggKind::Plain | AggKind::TimeWeightedScalar => { _ if true => {
use ScalarType::*; use ScalarType::*;
type K<T> = eventsdim1::EventsDim1<T>; type K<T> = eventsdim1::EventsDim1<T>;
match scalar_type { match scalar_type {
@@ -272,87 +273,23 @@ pub fn empty_events_dyn_ev(
STRING => Box::new(K::<String>::empty()), STRING => Box::new(K::<String>::empty()),
} }
} }
AggKind::PulseIdDiff => Box::new(eventsdim0::EventsDim0::<i64>::empty()), _ if true => Box::new(eventsdim0::EventsDim0::<i64>::empty()),
AggKind::DimXBins1 | AggKind::DimXBinsN(..) | AggKind::EventBlobs => { _ => {
error!("TODO empty_events_dyn_ev {agg_kind:?} {scalar_type:?} {shape:?}"); error!("TODO empty_events_dyn_ev {transform:?} {scalar_type:?} {shape:?}");
err::todoval() err::todoval()
} }
}, },
Shape::Image(..) => { Shape::Image(..) => {
error!("TODO empty_events_dyn_ev {agg_kind:?} {scalar_type:?} {shape:?}"); error!("TODO empty_events_dyn_ev {transform:?} {scalar_type:?} {shape:?}");
err::todoval() err::todoval()
} }
}; };
Ok(ret) Ok(ret)
} }
pub fn empty_binned_dyn_tb(scalar_type: &ScalarType, shape: &Shape, agg_kind: &AggKind) -> Box<dyn TimeBinnable> { pub fn empty_binned_dyn_tb(scalar_type: &ScalarType, shape: &Shape, transform: &Transform) -> Box<dyn TimeBinnable> {
match shape { error!("TODO empty_binned_dyn_tb");
Shape::Scalar => match agg_kind { todo!()
AggKind::TimeWeightedScalar => {
use ScalarType::*;
type K<T> = binsdim0::BinsDim0<T>;
match scalar_type {
U8 => Box::new(K::<u8>::empty()),
U16 => Box::new(K::<u16>::empty()),
U32 => Box::new(K::<u32>::empty()),
U64 => Box::new(K::<u64>::empty()),
I8 => Box::new(K::<i8>::empty()),
I16 => Box::new(K::<i16>::empty()),
I32 => Box::new(K::<i32>::empty()),
I64 => Box::new(K::<i64>::empty()),
F32 => Box::new(K::<f32>::empty()),
F64 => Box::new(K::<f64>::empty()),
BOOL | STRING => {
error!("TODO empty_binned_dyn_tb {agg_kind:?} {scalar_type:?} {shape:?}");
err::todoval()
}
}
}
AggKind::Plain
| AggKind::DimXBins1
| AggKind::DimXBinsN(..)
| AggKind::EventBlobs
| AggKind::PulseIdDiff => {
error!("TODO empty_binned_dyn_tb {agg_kind:?} {scalar_type:?} {shape:?}");
err::todoval()
}
},
Shape::Wave(_n) => match agg_kind {
AggKind::DimXBins1 => {
use ScalarType::*;
type K<T> = binsdim0::BinsDim0<T>;
match scalar_type {
U8 => Box::new(K::<u8>::empty()),
U16 => Box::new(K::<u16>::empty()),
U32 => Box::new(K::<u32>::empty()),
U64 => Box::new(K::<u64>::empty()),
I8 => Box::new(K::<i8>::empty()),
I16 => Box::new(K::<i16>::empty()),
I32 => Box::new(K::<i32>::empty()),
I64 => Box::new(K::<i64>::empty()),
F32 => Box::new(K::<f32>::empty()),
F64 => Box::new(K::<f64>::empty()),
BOOL | STRING => {
error!("TODO empty_binned_dyn_tb {agg_kind:?} {scalar_type:?} {shape:?}");
err::todoval()
}
}
}
AggKind::EventBlobs
| AggKind::DimXBinsN(..)
| AggKind::Plain
| AggKind::TimeWeightedScalar
| AggKind::PulseIdDiff => {
error!("TODO empty_binned_dyn_tb {agg_kind:?} {scalar_type:?} {shape:?}");
err::todoval()
}
},
Shape::Image(..) => {
error!("TODO empty_binned_dyn_tb {agg_kind:?} {scalar_type:?} {shape:?}");
err::todoval()
}
}
} }
fn flush_binned( fn flush_binned(
@@ -399,6 +336,7 @@ pub async fn binned_collected(
inp: Pin<Box<dyn Stream<Item = Sitemty<ChannelEvents>> + Send>>, inp: Pin<Box<dyn Stream<Item = Sitemty<ChannelEvents>> + Send>>,
) -> Result<Box<dyn ToJsonResult>, Error> { ) -> Result<Box<dyn ToJsonResult>, Error> {
event!(Level::TRACE, "binned_collected"); event!(Level::TRACE, "binned_collected");
let transform = Transform::default_time_binned();
let edges = binrange.edges(); let edges = binrange.edges();
if edges.len() < 2 { if edges.len() < 2 {
return Err(format!("binned_collected but edges.len() {}", edges.len()).into()); return Err(format!("binned_collected but edges.len() {}", edges.len()).into());
@@ -414,7 +352,7 @@ pub async fn binned_collected(
let mut did_range_complete = false; let mut did_range_complete = false;
let mut coll = None; let mut coll = None;
let mut binner = None; let mut binner = None;
let empty_item = empty_events_dyn_ev(&scalar_type, &shape, &AggKind::TimeWeightedScalar)?; let empty_item = empty_events_dyn_ev(&scalar_type, &shape, &transform)?;
let tmp_item = Ok(StreamItem::DataItem(RangeCompletableItem::Data(ChannelEvents::Events( let tmp_item = Ok(StreamItem::DataItem(RangeCompletableItem::Data(ChannelEvents::Events(
empty_item, empty_item,
)))); ))));
@@ -502,7 +440,7 @@ pub async fn binned_collected(
} }
None => { None => {
error!("binned_collected nothing collected"); error!("binned_collected nothing collected");
let item = empty_binned_dyn_tb(&scalar_type, &shape, &AggKind::DimXBins1); let item = empty_binned_dyn_tb(&scalar_type, &shape, &transform);
let ret = item.to_box_to_json_result(); let ret = item.to_box_to_json_result();
tokio::time::sleep(Duration::from_millis(2000)).await; tokio::time::sleep(Duration::from_millis(2000)).await;
Ok(ret) Ok(ret)
+238 -244
View File
@@ -13,7 +13,6 @@ use futures_util::{Stream, StreamExt};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Value as JsVal; use serde_json::Value as JsVal;
use std::collections::{BTreeMap, VecDeque}; use std::collections::{BTreeMap, VecDeque};
use std::fmt;
use std::iter::FromIterator; use std::iter::FromIterator;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::path::PathBuf; use std::path::PathBuf;
@@ -21,6 +20,7 @@ use std::pin::Pin;
use std::str::FromStr; use std::str::FromStr;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use std::time::Duration; use std::time::Duration;
use std::{fmt, ops};
use timeunits::*; use timeunits::*;
use url::Url; use url::Url;
@@ -757,6 +757,30 @@ impl NanoRange {
} }
} }
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct PulseRange {
pub beg: u64,
pub end: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum SeriesRange {
TimeRange(NanoRange),
PulseRange(PulseRange),
}
impl From<NanoRange> for SeriesRange {
fn from(k: NanoRange) -> Self {
Self::TimeRange(k)
}
}
impl From<PulseRange> for SeriesRange {
fn from(k: PulseRange) -> Self {
Self::PulseRange(k)
}
}
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ByteOrder { pub enum ByteOrder {
Little, Little,
@@ -1087,13 +1111,32 @@ pub mod timeunits {
pub const DAY: u64 = HOUR * 24; pub const DAY: u64 = HOUR * 24;
} }
const BIN_T_LEN_OPTIONS_0: [u64; 3] = [ pub trait Dim0Index: Clone + fmt::Debug + ops::Add + ops::Sub + PartialOrd {
// fn times(&self, x: u64) -> Self;
//SEC, fn div_n(&self, n: u64) -> Self;
MIN * 1, fn as_u64(&self) -> u64;
HOUR * 1, fn series_range(a: Self, b: Self) -> SeriesRange;
DAY, fn prebin_bin_len_opts() -> &'static [Self];
]; fn prebin_patch_len_for(i: usize) -> Self;
fn to_pre_binned_patch_range_enum(
bin_len: Self,
bin_count: u64,
patch_offset: u64,
patch_count: u64,
) -> PreBinnedPatchRangeEnum;
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TsNano(u64);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PulseId(u64);
impl Dim0Index for TsNano {}
impl Dim0Index for PulseId {}
const PREBIN_TIME_BIN_LEN_VAR0: [TsNano; 3] = [TsNano(MIN * 1), TsNano(HOUR * 1), TsNano(DAY)];
const PATCH_T_LEN_OPTIONS_SCALAR: [u64; 3] = [ const PATCH_T_LEN_OPTIONS_SCALAR: [u64; 3] = [
// //
@@ -1111,7 +1154,7 @@ const PATCH_T_LEN_OPTIONS_WAVE: [u64; 3] = [
DAY * 32, DAY * 32,
]; ];
const BIN_THRESHOLDS: [u64; 39] = [ const TIME_BIN_THRESHOLDS: [u64; 39] = [
MU, MU,
MU * 2, MU * 2,
MU * 5, MU * 5,
@@ -1153,130 +1196,115 @@ const BIN_THRESHOLDS: [u64; 39] = [
DAY * 64, DAY * 64,
]; ];
#[derive(Clone, Serialize, Deserialize)] const PULSE_BIN_THRESHOLDS: [u64; 10] = [
pub struct PreBinnedPatchGridSpec { 10, 20, 40, 80, 100, 200, 400, 800, 1000, 2000, 4000, 8000, 10000, 20000, 40000, 80000, 100000, 200000, 400000,
bin_t_len: u64, 800000, 1000000, 2000000, 4000000, 8000000, 10000000,
patch_t_len: u64, ];
const fn time_bin_threshold_at(i: usize) -> TsNano {
TsNano(TIME_BIN_THRESHOLDS[i])
} }
impl PreBinnedPatchGridSpec { const fn pulse_bin_threshold_at(i: usize) -> PulseId {
pub fn new(bin_t_len: u64, patch_t_len: u64) -> Self { PulseId(PULSE_BIN_THRESHOLDS[i])
if !Self::is_valid_bin_t_len(bin_t_len) { }
panic!("PreBinnedPatchGridSpec invalid bin_t_len {}", bin_t_len);
/// Identifies one patch on the binning grid at a certain resolution.
/// A patch consists of `bin_count` consecutive bins.
/// In total, a given `PreBinnedPatchCoord` spans a time range from `patch_beg` to `patch_end`.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PreBinnedPatchCoord<T>
where
T: Dim0Index,
{
bin_len: T,
bin_count: u64,
patch_offset: u64,
}
impl<T> PreBinnedPatchCoord<T>
where
T: Dim0Index,
{
pub fn new(bin_len: T, bin_count: u64, patch_offset: u64) -> Self {
Self {
bin_len,
bin_count,
patch_offset,
} }
Self { bin_t_len, patch_t_len } }
pub fn bin_len(&self) -> T {
self.bin_len
} }
pub fn bin_t_len(&self) -> u64 { pub fn patch_len(&self) -> T {
self.bin_t_len self.bin_len().times(self.bin_count)
} }
pub fn is_valid_bin_t_len(bin_t_len: u64) -> bool { pub fn patch_beg(&self) -> T {
for &j in BIN_T_LEN_OPTIONS_0.iter() { self.bin_len().times(self.bin_count).times(self.patch_offset)
if bin_t_len == j { }
return true;
} pub fn patch_end(&self) -> T {
self.bin_len().times(self.bin_count).times(1 + self.patch_offset)
}
pub fn series_range(&self) -> SeriesRange {
T::series_range(self.patch_beg(), self.patch_end())
}
pub fn bin_count(&self) -> u64 {
self.bin_count
}
pub fn patch_offset(&self) -> u64 {
self.patch_offset
}
pub fn edges(&self) -> Vec<T> {
let mut ret = Vec::new();
let mut t = self.patch_beg();
ret.push(t);
for _ in 0..self.bin_count() {
t += self.bin_t_len();
ret.push(t);
} }
return false; ret
} }
pub fn patch_t_len(&self) -> u64 { pub fn next(&self) -> Self {
self.patch_t_len Self::new(self.bin_len, self.bin_count, 1 + self.patch_offset)
} }
} }
impl std::fmt::Debug for PreBinnedPatchGridSpec { impl<T> AppendToUrl for PreBinnedPatchCoord<T>
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { where
fmt.debug_struct("PreBinnedPatchGridSpec") T: Dim0Index,
.field("bin_t_len", &(self.bin_t_len / SEC)) {
.field("patch_t_len", &(self.patch_t_len() / SEC)) fn append_to_url(&self, url: &mut Url) {
.finish_non_exhaustive() error!("TODO AppendToUrl for PreBinnedPatchCoord");
err::todo();
// TODO must also emit the type of the series index
let mut g = url.query_pairs_mut();
g.append_pair("patchTlen", &format!("{}", 4242));
} }
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PreBinnedPatchRange { pub struct PreBinnedPatchRange<T>
pub grid_spec: PreBinnedPatchGridSpec, where
pub offset: u64, T: Dim0Index,
pub count: u64, {
first: PreBinnedPatchCoord<T>,
patch_count: u64,
} }
fn get_patch_t_len(bin_t_len: u64) -> u64 { impl<T> PreBinnedPatchRange<T>
// TODO mechanism to select different patch lengths for different channels. where
let shape = Shape::Scalar; T: Dim0Index,
match shape { {
Shape::Scalar => {
for (i1, &j) in BIN_T_LEN_OPTIONS_0.iter().enumerate() {
if bin_t_len == j {
return PATCH_T_LEN_OPTIONS_SCALAR[i1];
}
}
}
Shape::Wave(..) => {
for (i1, &j) in BIN_T_LEN_OPTIONS_0.iter().enumerate() {
if bin_t_len == j {
return PATCH_T_LEN_OPTIONS_WAVE[i1];
}
}
}
Shape::Image(..) => {
for (i1, &j) in BIN_T_LEN_OPTIONS_0.iter().enumerate() {
if bin_t_len == j {
return PATCH_T_LEN_OPTIONS_WAVE[i1];
}
}
}
}
panic!()
}
impl PreBinnedPatchRange {
/// Cover at least the given range with at least as many as the requested number of bins.
pub fn covering_range(range: NanoRange, min_bin_count: u32) -> Result<Option<Self>, Error> {
let bin_t_len_options = &BIN_T_LEN_OPTIONS_0;
if min_bin_count < 1 {
Err(Error::with_msg("min_bin_count < 1"))?;
}
if min_bin_count > 20000 {
Err(Error::with_msg(format!("min_bin_count > 20000: {}", min_bin_count)))?;
}
let dt = range.delta();
if dt > DAY * 200 {
Err(Error::with_msg("dt > DAY * 200"))?;
}
let bs = dt / min_bin_count as u64;
let mut i1 = bin_t_len_options.len();
loop {
if i1 == 0 {
break Ok(None);
} else {
i1 -= 1;
let t = bin_t_len_options[i1];
if t <= bs {
let bin_t_len = t;
let patch_t_len = get_patch_t_len(bin_t_len);
if !PreBinnedPatchGridSpec::is_valid_bin_t_len(bin_t_len) {
return Err(Error::with_msg_no_trace(format!("not a valid bin_t_len {}", bin_t_len)));
}
let grid_spec = PreBinnedPatchGridSpec { bin_t_len, patch_t_len };
let pl = patch_t_len;
let ts1 = range.beg / pl * pl;
let ts2 = (range.end + pl - 1) / pl * pl;
let count = (ts2 - ts1) / pl;
let offset = ts1 / pl;
let ret = Self {
grid_spec,
count,
offset,
};
break Ok(Some(ret));
}
}
}
}
pub fn edges(&self) -> Vec<u64> { pub fn edges(&self) -> Vec<u64> {
let mut ret = vec![]; let mut ret = Vec::new();
let mut t = self.grid_spec.patch_t_len() * self.offset; let mut t = self.grid_spec.patch_t_len() * self.offset;
ret.push(t); ret.push(t);
let bin_count = self.grid_spec.patch_t_len() / self.grid_spec.bin_t_len() * self.count; let bin_count = self.grid_spec.patch_t_len() / self.grid_spec.bin_t_len() * self.count;
@@ -1309,152 +1337,75 @@ impl PreBinnedPatchRange {
} }
} }
/// Identifies one patch on the binning grid at a certain resolution. pub enum PreBinnedPatchRangeEnum {
/// A patch consists of `bin_count` consecutive bins. Time(PreBinnedPatchRange<TsNano>),
/// In total, a given `PreBinnedPatchCoord` spans a time range from `patch_beg` to `patch_end`. Pulse(PreBinnedPatchRange<PulseId>),
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PreBinnedPatchCoord {
spec: PreBinnedPatchGridSpec,
ix: u64,
} }
impl PreBinnedPatchCoord { impl PreBinnedPatchRangeEnum {
pub fn bin_t_len(&self) -> u64 { fn covering_range_ty<T>(a: T, b: T, min_bin_count: u32) -> Result<Self, Error>
self.spec.bin_t_len where
} T: Dim0Index,
{
pub fn patch_t_len(&self) -> u64 { let opts = T::prebin_bin_len_opts();
self.spec.patch_t_len() if min_bin_count < 1 {
} Err(Error::with_msg("min_bin_count < 1"))?;
pub fn patch_beg(&self) -> u64 {
self.spec.patch_t_len() * self.ix
}
pub fn patch_end(&self) -> u64 {
self.spec.patch_t_len() * (self.ix + 1)
}
pub fn patch_range(&self) -> NanoRange {
NanoRange {
beg: self.patch_beg(),
end: self.patch_end(),
} }
} if min_bin_count > 20000 {
Err(Error::with_msg(format!("min_bin_count > 20000: {}", min_bin_count)))?;
pub fn bin_count(&self) -> u32 {
(self.spec.patch_t_len() / self.spec.bin_t_len) as u32
}
pub fn spec(&self) -> &PreBinnedPatchGridSpec {
&self.spec
}
pub fn ix(&self) -> u64 {
self.ix
}
pub fn new(bin_t_len: u64, patch_t_len: u64, patch_ix: u64) -> Self {
Self {
spec: PreBinnedPatchGridSpec::new(bin_t_len, patch_t_len),
ix: patch_ix,
} }
} let du = b - a;
let max_bin_len = du.div_n(min_bin_count);
pub fn edges(&self) -> Vec<u64> { for (i1, bl) in opts.enumerate().rev() {
let mut ret = vec![]; if bl <= du {
let mut t = self.patch_beg(); let patch_len = bl.prebin_patch_len_for(i1);
ret.push(t); let bin_count = patch_len.div_v(bl);
for _ in 0..self.bin_count() { let patch_off_1 = a.div_v(&patch_len);
t += self.bin_t_len(); let patch_off_2 = b.div_v(&patch_len.add(patch_len).sub(1));
ret.push(t); //patch_off_2.sub(patch_off_1);
} let patch_count = patch_off_2 - patch_off_1;
ret let ret = T::to_pre_binned_patch_range_enum(bl, bin_count, patch_off_1, patch_count);
} return Ok(ret);
}
impl AppendToUrl for PreBinnedPatchCoord {
fn append_to_url(&self, url: &mut Url) {
let mut g = url.query_pairs_mut();
g.append_pair("patchTlen", &format!("{}", self.spec.patch_t_len() / SEC));
g.append_pair("binTlen", &format!("{}", self.spec.bin_t_len() / SEC));
g.append_pair("patchIx", &format!("{}", self.ix()));
}
}
pub struct PreBinnedPatchIterator {
range: PreBinnedPatchRange,
ix: u64,
}
impl PreBinnedPatchIterator {
pub fn from_range(range: PreBinnedPatchRange) -> Self {
Self { range, ix: 0 }
}
}
impl Iterator for PreBinnedPatchIterator {
type Item = PreBinnedPatchCoord;
fn next(&mut self) -> Option<Self::Item> {
if self.ix >= self.range.count {
None
} else {
let ret = Self::Item {
spec: self.range.grid_spec.clone(),
ix: self.range.offset + self.ix,
};
self.ix += 1;
Some(ret)
}
}
}
#[derive(Clone, Serialize, Deserialize)]
pub struct BinnedGridSpec {
bin_t_len: u64,
}
impl BinnedGridSpec {
pub fn new(bin_t_len: u64) -> Self {
if !Self::is_valid_bin_t_len(bin_t_len) {
panic!("BinnedGridSpec::new invalid bin_t_len {}", bin_t_len);
}
Self { bin_t_len }
}
pub fn bin_t_len(&self) -> u64 {
self.bin_t_len
}
pub fn is_valid_bin_t_len(bin_t_len: u64) -> bool {
for &j in BIN_T_LEN_OPTIONS_0.iter() {
if bin_t_len == j {
return true;
} }
} }
return false; Err(Error::with_msg_no_trace("can not find matching pre-binned grid"))
} }
}
impl fmt::Debug for BinnedGridSpec { /// Cover at least the given range with at least as many as the requested number of bins.
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { pub fn covering_range(range: SeriesRange, min_bin_count: u32) -> Result<Self, Error> {
if self.bin_t_len < SEC * 90 { match range {
write!(fmt, "BinnedGridSpec {{ bin_t_len: {:?} ms }}", self.bin_t_len / MS,) SeriesRange::TimeRange(k) => Self::covering_range_ty(TsNano(k.beg), TsNano(k.end), min_bin_count),
} else { SeriesRange::PulseRange(k) => Self::covering_range_ty(PulseId(k.beg), PulseId(k.end), min_bin_count),
write!(fmt, "BinnedGridSpec {{ bin_t_len: {:?} s }}", self.bin_t_len / SEC,)
} }
} }
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BinnedRange { pub struct BinnedRange<T>
grid_spec: BinnedGridSpec, where
offset: u64, T: Dim0Index,
bin_count: u64, {
bin_len: T,
bin_off: u64,
bin_cnt: u64,
} }
impl BinnedRange { impl<T> fmt::Debug for BinnedRange<T>
where
T: Dim0Index,
{
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("BinnedRange")
.field("bin_len", &self.bin_len)
.field("bin_off", &self.bin_off)
.field("bin_cnt", &self.bin_cnt)
}
}
impl<T> BinnedRange<T>
where
T: Dim0Index,
{
pub fn covering_range(range: NanoRange, min_bin_count: u32) -> Result<Self, Error> { pub fn covering_range(range: NanoRange, min_bin_count: u32) -> Result<Self, Error> {
let thresholds = &BIN_THRESHOLDS; let thresholds = &BIN_THRESHOLDS;
if min_bin_count < 1 { if min_bin_count < 1 {
@@ -1528,6 +1479,49 @@ impl BinnedRange {
} }
} }
pub enum BinnedRangeEnum {
Time(PreBinnedPatchRange<TsNano>),
Pulse(PreBinnedPatchRange<PulseId>),
}
impl BinnedRangeEnum {
fn covering_range_ty<T>(a: T, b: T, min_bin_count: u32) -> Result<Self, Error>
where
T: Dim0Index,
{
let opts = T::prebin_bin_len_opts();
if min_bin_count < 1 {
Err(Error::with_msg("min_bin_count < 1"))?;
}
if min_bin_count > 20000 {
Err(Error::with_msg(format!("min_bin_count > 20000: {}", min_bin_count)))?;
}
let du = b - a;
let max_bin_len = du.div_n(min_bin_count);
for (i1, bl) in opts.enumerate().rev() {
if bl <= du {
let patch_len = bl.prebin_patch_len_for(i1);
let bin_count = patch_len.div_v(bl);
let patch_off_1 = a.div_v(&patch_len);
let patch_off_2 = b.div_v(&patch_len.add(patch_len).sub(1));
//patch_off_2.sub(patch_off_1);
let patch_count = patch_off_2 - patch_off_1;
let ret = T::to_pre_binned_patch_range_enum(bl, bin_count, patch_off_1, patch_count);
return Ok(ret);
}
}
Err(Error::with_msg_no_trace("can not find matching pre-binned grid"))
}
/// Cover at least the given range with at least as many as the requested number of bins.
pub fn covering_range(range: SeriesRange, min_bin_count: u32) -> Result<Self, Error> {
match range {
SeriesRange::TimeRange(k) => Self::covering_range_ty(TsNano(k.beg), TsNano(k.end), min_bin_count),
SeriesRange::PulseRange(k) => Self::covering_range_ty(PulseId(k.beg), PulseId(k.end), min_bin_count),
}
}
}
#[cfg(test)] #[cfg(test)]
mod test_binned_range { mod test_binned_range {
use super::*; use super::*;
+203 -100
View File
@@ -14,6 +14,8 @@ use crate::FromUrl;
use crate::HasBackend; use crate::HasBackend;
use crate::HasTimeout; use crate::HasTimeout;
use crate::NanoRange; use crate::NanoRange;
use crate::PulseRange;
use crate::SeriesRange;
use crate::ToNanos; use crate::ToNanos;
use chrono::DateTime; use chrono::DateTime;
use chrono::TimeZone; use chrono::TimeZone;
@@ -81,14 +83,134 @@ impl fmt::Display for CacheUsage {
} }
} }
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TimeRangeQuery {
range: NanoRange,
}
impl FromUrl for TimeRangeQuery {
fn from_url(url: &Url) -> Result<Self, Error> {
let pairs = get_url_query_pairs(url);
Self::from_pairs(&pairs)
}
fn from_pairs(pairs: &BTreeMap<String, String>) -> Result<Self, Error> {
if let (Some(beg), Some(end)) = (pairs.get("begDate"), pairs.get("endDate")) {
let ret = Self {
range: NanoRange {
beg: beg.parse::<DateTime<Utc>>()?.to_nanos(),
end: end.parse::<DateTime<Utc>>()?.to_nanos(),
},
};
Ok(ret)
} else if let (Some(beg), Some(end)) = (pairs.get("begNs"), pairs.get("endNs")) {
let ret = Self {
range: NanoRange {
beg: beg.parse()?,
end: end.parse()?,
},
};
Ok(ret)
} else {
Err(Error::with_public_msg("missing date range"))
}
}
}
impl AppendToUrl for TimeRangeQuery {
fn append_to_url(&self, url: &mut Url) {
let date_fmt = "%Y-%m-%dT%H:%M:%S.%6fZ";
let mut g = url.query_pairs_mut();
g.append_pair(
"begDate",
&Utc.timestamp_nanos(self.range.beg as i64).format(date_fmt).to_string(),
);
g.append_pair(
"endDate",
&Utc.timestamp_nanos(self.range.end as i64).format(date_fmt).to_string(),
);
}
}
impl From<TimeRangeQuery> for NanoRange {
fn from(k: TimeRangeQuery) -> Self {
Self {
beg: k.range.beg,
end: k.range.end,
}
}
}
impl From<&NanoRange> for TimeRangeQuery {
fn from(k: &NanoRange) -> Self {
Self {
range: NanoRange { beg: k.beg, end: k.end },
}
}
}
impl From<&PulseRange> for PulseRangeQuery {
fn from(k: &PulseRange) -> Self {
Self {
range: PulseRange { beg: k.beg, end: k.end },
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PulseRangeQuery {
range: PulseRange,
}
impl FromUrl for PulseRangeQuery {
fn from_url(url: &Url) -> Result<Self, Error> {
let pairs = get_url_query_pairs(url);
Self::from_pairs(&pairs)
}
fn from_pairs(pairs: &BTreeMap<String, String>) -> Result<Self, Error> {
if let (Some(beg), Some(end)) = (pairs.get("begPulse"), pairs.get("endPulse")) {
let ret = Self {
range: PulseRange {
beg: beg.parse()?,
end: end.parse()?,
},
};
Ok(ret)
} else {
Err(Error::with_public_msg("missing pulse range"))
}
}
}
impl AppendToUrl for PulseRangeQuery {
fn append_to_url(&self, url: &mut Url) {
let mut g = url.query_pairs_mut();
g.append_pair("begPulse", &self.range.beg.to_string());
g.append_pair("endPulse", &self.range.end.to_string());
}
}
impl From<PulseRangeQuery> for PulseRange {
fn from(k: PulseRangeQuery) -> Self {
Self {
beg: k.range.beg,
end: k.range.end,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PlainEventsQuery { pub struct PlainEventsQuery {
channel: Channel, channel: Channel,
range: NanoRange, range: SeriesRange,
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "is_false", rename = "oneBeforeRange")]
agg_kind: Option<AggKind>, one_before_range: bool,
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(
transform: Option<Transform>, default = "Transform::default_events",
skip_serializing_if = "Transform::is_default_events"
)]
transform: Transform,
#[serde(default, skip_serializing_if = "Option::is_none", with = "humantime_serde")] #[serde(default, skip_serializing_if = "Option::is_none", with = "humantime_serde")]
timeout: Option<Duration>, timeout: Option<Duration>,
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Option::is_none")]
@@ -106,20 +228,17 @@ pub struct PlainEventsQuery {
} }
impl PlainEventsQuery { impl PlainEventsQuery {
pub fn new( pub fn new<R>(channel: Channel, range: R) -> Self
channel: Channel, where
range: NanoRange, R: Into<SeriesRange>,
agg_kind: Option<AggKind>, {
timeout: Option<Duration>,
events_max: Option<u64>,
) -> Self {
Self { Self {
channel, channel,
range, range: range.into(),
agg_kind, one_before_range: false,
transform: None, transform: Transform::default_events(),
timeout, timeout: Some(Duration::from_millis(4000)),
events_max, events_max: Some(10000),
event_delay: None, event_delay: None,
stream_batch_len: None, stream_batch_len: None,
buf_len_disk_io: None, buf_len_disk_io: None,
@@ -132,23 +251,16 @@ impl PlainEventsQuery {
&self.channel &self.channel
} }
pub fn range(&self) -> &NanoRange { pub fn range(&self) -> &SeriesRange {
&self.range &self.range
} }
pub fn agg_kind(&self) -> &Option<AggKind> {
&self.agg_kind
}
pub fn agg_kind_value(&self) -> AggKind {
self.agg_kind.as_ref().map_or(AggKind::Plain, |x| x.clone())
}
pub fn one_before_range(&self) -> bool { pub fn one_before_range(&self) -> bool {
match &self.agg_kind { self.one_before_range
Some(k) => k.need_expand(), }
None => false,
} pub fn transform(&self) -> &Transform {
&self.transform
} }
pub fn buf_len_disk_io(&self) -> usize { pub fn buf_len_disk_io(&self) -> usize {
@@ -206,17 +318,19 @@ impl FromUrl for PlainEventsQuery {
Self::from_pairs(&pairs) Self::from_pairs(&pairs)
} }
fn from_pairs(pairs: &std::collections::BTreeMap<String, String>) -> Result<Self, Error> { fn from_pairs(pairs: &BTreeMap<String, String>) -> Result<Self, Error> {
let beg_date = pairs.get("begDate").ok_or(Error::with_public_msg("missing begDate"))?; let range = if let Ok(x) = TimeRangeQuery::from_pairs(pairs) {
let end_date = pairs.get("endDate").ok_or(Error::with_public_msg("missing endDate"))?; SeriesRange::TimeRange(x.into())
} else if let Ok(x) = PulseRangeQuery::from_pairs(pairs) {
SeriesRange::PulseRange(x.into())
} else {
return Err(Error::with_msg_no_trace("no series range in url"));
};
let ret = Self { let ret = Self {
channel: Channel::from_pairs(pairs)?, channel: Channel::from_pairs(pairs)?,
range: NanoRange { range,
beg: beg_date.parse::<DateTime<Utc>>()?.to_nanos(), one_before_range: pairs.get("oneBeforeRange").map_or("false", |x| x.as_ref()) == "true",
end: end_date.parse::<DateTime<Utc>>()?.to_nanos(), transform: Transform::from_pairs(pairs)?,
},
agg_kind: agg_kind_from_binning_scheme(pairs)?,
transform: Some(Transform::from_pairs(pairs)?),
timeout: pairs timeout: pairs
.get("timeout") .get("timeout")
.map(|x| x.parse::<u64>().map(Duration::from_millis).ok()) .map(|x| x.parse::<u64>().map(Duration::from_millis).ok())
@@ -250,23 +364,19 @@ impl FromUrl for PlainEventsQuery {
impl AppendToUrl for PlainEventsQuery { impl AppendToUrl for PlainEventsQuery {
fn append_to_url(&self, url: &mut Url) { fn append_to_url(&self, url: &mut Url) {
let date_fmt = "%Y-%m-%dT%H:%M:%S.%6fZ"; match &self.range {
SeriesRange::TimeRange(k) => TimeRangeQuery::from(k).append_to_url(url),
SeriesRange::PulseRange(_) => todo!(),
}
self.channel.append_to_url(url); self.channel.append_to_url(url);
if let Some(x) = &self.transform { {
x.append_to_url(url); let mut g = url.query_pairs_mut();
} if self.one_before_range() {
if let Some(x) = &self.agg_kind { g.append_pair("oneBeforeRange", "true");
binning_scheme_append_to_url(x, url); }
} }
self.transform.append_to_url(url);
let mut g = url.query_pairs_mut(); let mut g = url.query_pairs_mut();
g.append_pair(
"begDate",
&Utc.timestamp_nanos(self.range.beg as i64).format(date_fmt).to_string(),
);
g.append_pair(
"endDate",
&Utc.timestamp_nanos(self.range.end as i64).format(date_fmt).to_string(),
);
if let Some(x) = &self.timeout { if let Some(x) = &self.timeout {
g.append_pair("timeout", &format!("{}", x.as_millis())); g.append_pair("timeout", &format!("{}", x.as_millis()));
} }
@@ -294,10 +404,13 @@ impl AppendToUrl for PlainEventsQuery {
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BinnedQuery { pub struct BinnedQuery {
channel: Channel, channel: Channel,
range: NanoRange, range: SeriesRange,
bin_count: u32, bin_count: u32,
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(
agg_kind: Option<AggKind>, default = "Transform::default_time_binned",
skip_serializing_if = "Transform::is_default_time_binned"
)]
transform: Transform,
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Option::is_none")]
cache_usage: Option<CacheUsage>, cache_usage: Option<CacheUsage>,
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Option::is_none")]
@@ -311,12 +424,12 @@ pub struct BinnedQuery {
} }
impl BinnedQuery { impl BinnedQuery {
pub fn new(channel: Channel, range: NanoRange, bin_count: u32, agg_kind: Option<AggKind>) -> Self { pub fn new(channel: Channel, range: SeriesRange, bin_count: u32) -> Self {
Self { Self {
channel, channel,
range, range,
bin_count, bin_count,
agg_kind, transform: Transform::default_time_binned(),
cache_usage: None, cache_usage: None,
bins_max: None, bins_max: None,
buf_len_disk_io: None, buf_len_disk_io: None,
@@ -325,7 +438,7 @@ impl BinnedQuery {
} }
} }
pub fn range(&self) -> &NanoRange { pub fn range(&self) -> &SeriesRange {
&self.range &self.range
} }
@@ -337,11 +450,8 @@ impl BinnedQuery {
self.bin_count self.bin_count
} }
pub fn agg_kind(&self) -> AggKind { pub fn transform(&self) -> &Transform {
match &self.agg_kind { &self.transform
Some(x) => x.clone(),
None => AggKind::TimeWeightedScalar,
}
} }
pub fn cache_usage(&self) -> CacheUsage { pub fn cache_usage(&self) -> CacheUsage {
@@ -421,20 +531,22 @@ impl FromUrl for BinnedQuery {
} }
fn from_pairs(pairs: &BTreeMap<String, String>) -> Result<Self, Error> { fn from_pairs(pairs: &BTreeMap<String, String>) -> Result<Self, Error> {
let beg_date = pairs.get("begDate").ok_or(Error::with_msg("missing begDate"))?; let range = if let Ok(x) = TimeRangeQuery::from_pairs(pairs) {
let end_date = pairs.get("endDate").ok_or(Error::with_msg("missing endDate"))?; SeriesRange::TimeRange(x.into())
} else if let Ok(x) = PulseRangeQuery::from_pairs(pairs) {
SeriesRange::PulseRange(x.into())
} else {
return Err(Error::with_msg_no_trace("no series range in url"));
};
let ret = Self { let ret = Self {
channel: Channel::from_pairs(&pairs)?, channel: Channel::from_pairs(&pairs)?,
range: NanoRange { range,
beg: beg_date.parse::<DateTime<Utc>>()?.to_nanos(),
end: end_date.parse::<DateTime<Utc>>()?.to_nanos(),
},
bin_count: pairs bin_count: pairs
.get("binCount") .get("binCount")
.ok_or(Error::with_msg("missing binCount"))? .ok_or(Error::with_msg("missing binCount"))?
.parse() .parse()
.map_err(|e| Error::with_msg(format!("can not parse binCount {:?}", e)))?, .map_err(|e| Error::with_msg(format!("can not parse binCount {:?}", e)))?,
agg_kind: agg_kind_from_binning_scheme(&pairs)?, transform: Transform::from_pairs(pairs)?,
cache_usage: CacheUsage::from_pairs(&pairs)?, cache_usage: CacheUsage::from_pairs(&pairs)?,
buf_len_disk_io: pairs buf_len_disk_io: pairs
.get("bufLenDiskIo") .get("bufLenDiskIo")
@@ -462,40 +574,31 @@ impl FromUrl for BinnedQuery {
impl AppendToUrl for BinnedQuery { impl AppendToUrl for BinnedQuery {
fn append_to_url(&self, url: &mut Url) { fn append_to_url(&self, url: &mut Url) {
let date_fmt = "%Y-%m-%dT%H:%M:%S.%6fZ"; match &self.range {
SeriesRange::TimeRange(k) => TimeRangeQuery::from(k).append_to_url(url),
SeriesRange::PulseRange(k) => PulseRangeQuery::from(k).append_to_url(url),
}
self.channel.append_to_url(url);
{ {
self.channel.append_to_url(url);
let mut g = url.query_pairs_mut(); let mut g = url.query_pairs_mut();
if let Some(x) = &self.cache_usage {
g.append_pair("cacheUsage", &x.query_param_value());
}
g.append_pair(
"begDate",
&Utc.timestamp_nanos(self.range.beg as i64).format(date_fmt).to_string(),
);
g.append_pair(
"endDate",
&Utc.timestamp_nanos(self.range.end as i64).format(date_fmt).to_string(),
);
g.append_pair("binCount", &format!("{}", self.bin_count)); g.append_pair("binCount", &format!("{}", self.bin_count));
} }
if let Some(x) = &self.agg_kind { self.transform.append_to_url(url);
binning_scheme_append_to_url(x, url); let mut g = url.query_pairs_mut();
if let Some(x) = &self.cache_usage {
g.append_pair("cacheUsage", &x.query_param_value());
} }
{ if let Some(x) = &self.timeout {
let mut g = url.query_pairs_mut(); g.append_pair("timeout", &format!("{}", x.as_millis()));
if let Some(x) = &self.timeout { }
g.append_pair("timeout", &format!("{}", x.as_millis())); if let Some(x) = self.bins_max {
} g.append_pair("binsMax", &format!("{}", x));
if let Some(x) = self.bins_max { }
g.append_pair("binsMax", &format!("{}", x)); if let Some(x) = self.buf_len_disk_io {
} g.append_pair("bufLenDiskIo", &format!("{}", x));
if let Some(x) = self.buf_len_disk_io { }
g.append_pair("bufLenDiskIo", &format!("{}", x)); if let Some(x) = &self.disk_stats_every {
} g.append_pair("diskStatsEveryKb", &format!("{}", x.bytes() / 1024));
if let Some(x) = &self.disk_stats_every {
g.append_pair("diskStatsEveryKb", &format!("{}", x.bytes() / 1024));
}
} }
} }
} }
+28 -14
View File
@@ -1,16 +1,14 @@
use crate::get_url_query_pairs; use crate::get_url_query_pairs;
use crate::log::*; use crate::log::*;
use crate::AppendToUrl; use crate::AppendToUrl;
use crate::BinnedRange;
use crate::FromUrl; use crate::FromUrl;
use crate::NanoRange;
use err::Error; use err::Error;
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use url::Url; use url::Url;
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum EventTransform { pub enum EventTransform {
EventBlobsVerbatim, EventBlobsVerbatim,
EventBlobsUncompressed, EventBlobsUncompressed,
@@ -20,14 +18,14 @@ pub enum EventTransform {
PulseIdDiff, PulseIdDiff,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum TimeBinningTransform { pub enum TimeBinningTransform {
None, None,
TimeWeighted(BinnedRange), TimeWeighted,
Unweighted(BinnedRange), Unweighted,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Transform { pub struct Transform {
event: EventTransform, event: EventTransform,
time_binning: TimeBinningTransform, time_binning: TimeBinningTransform,
@@ -37,6 +35,28 @@ impl Transform {
fn url_prefix() -> &'static str { fn url_prefix() -> &'static str {
"transform" "transform"
} }
pub fn default_events() -> Self {
Self {
event: EventTransform::ValueFull,
time_binning: TimeBinningTransform::None,
}
}
pub fn default_time_binned() -> Self {
Self {
event: EventTransform::MinMaxAvgDev,
time_binning: TimeBinningTransform::TimeWeighted,
}
}
pub fn is_default_events(&self) -> bool {
self == &Self::default_events()
}
pub fn is_default_time_binned(&self) -> bool {
self == &Self::default_time_binned()
}
} }
impl FromUrl for Transform { impl FromUrl for Transform {
@@ -62,13 +82,7 @@ impl FromUrl for Transform {
} else if s == "timeWeightedScalar" { } else if s == "timeWeightedScalar" {
Transform { Transform {
event: EventTransform::MinMaxAvgDev, event: EventTransform::MinMaxAvgDev,
time_binning: TimeBinningTransform::TimeWeighted(BinnedRange::covering_range( time_binning: TimeBinningTransform::TimeWeighted,
NanoRange {
beg: 20000000000,
end: 30000000000,
},
20,
)?),
} }
} else if s == "unweightedScalar" { } else if s == "unweightedScalar" {
Transform { Transform {
+28 -28
View File
@@ -13,6 +13,7 @@ use netpod::log::*;
use netpod::query::CacheUsage; use netpod::query::CacheUsage;
use netpod::query::PlainEventsQuery; use netpod::query::PlainEventsQuery;
use netpod::timeunits::*; use netpod::timeunits::*;
use netpod::transform::Transform;
use netpod::AggKind; use netpod::AggKind;
use netpod::ChannelTyped; use netpod::ChannelTyped;
use netpod::PreBinnedPatchCoord; use netpod::PreBinnedPatchCoord;
@@ -33,7 +34,6 @@ pub async fn read_cached_scylla(
series: u64, series: u64,
chn: &ChannelTyped, chn: &ChannelTyped,
coord: &PreBinnedPatchCoord, coord: &PreBinnedPatchCoord,
_agg_kind: AggKind,
scy: &ScySession, scy: &ScySession,
) -> Result<Option<Box<dyn TimeBinned>>, Error> { ) -> Result<Option<Box<dyn TimeBinned>>, Error> {
let vals = ( let vals = (
@@ -206,7 +206,8 @@ pub async fn fetch_uncached_data(
series: u64, series: u64,
chn: ChannelTyped, chn: ChannelTyped,
coord: PreBinnedPatchCoord, coord: PreBinnedPatchCoord,
agg_kind: AggKind, one_before_range: bool,
transform: Transform,
cache_usage: CacheUsage, cache_usage: CacheUsage,
scy: Arc<ScySession>, scy: Arc<ScySession>,
) -> Result<Option<(Box<dyn TimeBinned>, bool)>, Error> { ) -> Result<Option<(Box<dyn TimeBinned>, bool)>, Error> {
@@ -226,13 +227,16 @@ pub async fn fetch_uncached_data(
&chn, &chn,
coord.clone(), coord.clone(),
range, range,
agg_kind, one_before_range,
transform,
cache_usage.clone(), cache_usage.clone(),
scy.clone(), scy.clone(),
) )
.await .await
} }
Ok(None) => fetch_uncached_binned_events(series, &chn, coord.clone(), agg_kind, scy.clone()).await, Ok(None) => {
fetch_uncached_binned_events(series, &chn, coord.clone(), one_before_range, transform, scy.clone()).await
}
Err(e) => Err(e), Err(e) => Err(e),
}?; }?;
if true || complete { if true || complete {
@@ -265,7 +269,8 @@ pub fn fetch_uncached_data_box(
series: u64, series: u64,
chn: &ChannelTyped, chn: &ChannelTyped,
coord: &PreBinnedPatchCoord, coord: &PreBinnedPatchCoord,
agg_kind: AggKind, one_before_range: bool,
transform: Transform,
cache_usage: CacheUsage, cache_usage: CacheUsage,
scy: Arc<ScySession>, scy: Arc<ScySession>,
) -> Pin<Box<dyn Future<Output = Result<Option<(Box<dyn TimeBinned>, bool)>, Error>> + Send>> { ) -> Pin<Box<dyn Future<Output = Result<Option<(Box<dyn TimeBinned>, bool)>, Error>> + Send>> {
@@ -273,7 +278,8 @@ pub fn fetch_uncached_data_box(
series, series,
chn.clone(), chn.clone(),
coord.clone(), coord.clone(),
agg_kind, one_before_range,
transform,
cache_usage, cache_usage,
scy, scy,
)) ))
@@ -284,7 +290,8 @@ pub async fn fetch_uncached_higher_res_prebinned(
chn: &ChannelTyped, chn: &ChannelTyped,
coord: PreBinnedPatchCoord, coord: PreBinnedPatchCoord,
range: PreBinnedPatchRange, range: PreBinnedPatchRange,
agg_kind: AggKind, one_before_range: bool,
transform: Transform,
cache_usage: CacheUsage, cache_usage: CacheUsage,
scy: Arc<ScySession>, scy: Arc<ScySession>,
) -> Result<(Box<dyn TimeBinned>, bool), Error> { ) -> Result<(Box<dyn TimeBinned>, bool), Error> {
@@ -292,7 +299,7 @@ pub async fn fetch_uncached_higher_res_prebinned(
// TODO refine the AggKind scheme or introduce a new BinningOpts type and get time-weight from there. // TODO refine the AggKind scheme or introduce a new BinningOpts type and get time-weight from there.
let do_time_weight = true; let do_time_weight = true;
// We must produce some result with correct types even if upstream delivers nothing at all. // We must produce some result with correct types even if upstream delivers nothing at all.
let bin0 = empty_binned_dyn_tb(&chn.scalar_type, &chn.shape, &agg_kind); let bin0 = empty_binned_dyn_tb(&chn.scalar_type, &chn.shape, &transform);
let mut time_binner = bin0.time_binner_new(edges.clone(), do_time_weight); let mut time_binner = bin0.time_binner_new(edges.clone(), do_time_weight);
let mut complete = true; let mut complete = true;
let patch_it = PreBinnedPatchIterator::from_range(range.clone()); let patch_it = PreBinnedPatchIterator::from_range(range.clone());
@@ -304,7 +311,8 @@ pub async fn fetch_uncached_higher_res_prebinned(
series, series,
chn, chn,
&patch_coord, &patch_coord,
agg_kind.clone(), one_before_range,
transform.clone(),
cache_usage.clone(), cache_usage.clone(),
scy.clone(), scy.clone(),
) )
@@ -358,7 +366,8 @@ pub async fn fetch_uncached_binned_events(
series: u64, series: u64,
chn: &ChannelTyped, chn: &ChannelTyped,
coord: PreBinnedPatchCoord, coord: PreBinnedPatchCoord,
agg_kind: AggKind, one_before_range: bool,
transform: Transform,
scy: Arc<ScySession>, scy: Arc<ScySession>,
) -> Result<(Box<dyn TimeBinned>, bool), Error> { ) -> Result<(Box<dyn TimeBinned>, bool), Error> {
let edges = coord.edges(); let edges = coord.edges();
@@ -367,7 +376,7 @@ pub async fn fetch_uncached_binned_events(
// We must produce some result with correct types even if upstream delivers nothing at all. // We must produce some result with correct types even if upstream delivers nothing at all.
//let bin0 = empty_events_dyn_tb(&chn.scalar_type, &chn.shape, &agg_kind); //let bin0 = empty_events_dyn_tb(&chn.scalar_type, &chn.shape, &agg_kind);
//let mut time_binner = bin0.time_binner_new(edges.clone(), do_time_weight); //let mut time_binner = bin0.time_binner_new(edges.clone(), do_time_weight);
let mut time_binner = empty_events_dyn_ev(&chn.scalar_type, &chn.shape, &agg_kind)? let mut time_binner = empty_events_dyn_ev(&chn.scalar_type, &chn.shape, &transform)?
.as_time_binnable() .as_time_binnable()
.time_binner_new(edges.clone(), do_time_weight); .time_binner_new(edges.clone(), do_time_weight);
// TODO handle deadline better // TODO handle deadline better
@@ -376,19 +385,11 @@ pub async fn fetch_uncached_binned_events(
let deadline = deadline let deadline = deadline
.checked_add(Duration::from_millis(6000)) .checked_add(Duration::from_millis(6000))
.ok_or_else(|| Error::with_msg_no_trace(format!("deadline overflow")))?; .ok_or_else(|| Error::with_msg_no_trace(format!("deadline overflow")))?;
let do_one_before_range = agg_kind.need_expand(); let evq = PlainEventsQuery::new(chn.channel.clone(), coord.patch_range());
let evq = PlainEventsQuery::new(
chn.channel.clone(),
coord.patch_range(),
Some(agg_kind),
// TODO take from query
Some(Duration::from_millis(8000)),
None,
);
let mut events_dyn = EventsStreamScylla::new( let mut events_dyn = EventsStreamScylla::new(
series, series,
evq.range().clone(), evq.range().clone(),
do_one_before_range, one_before_range,
chn.scalar_type.clone(), chn.scalar_type.clone(),
chn.shape.clone(), chn.shape.clone(),
true, true,
@@ -466,22 +467,20 @@ pub async fn pre_binned_value_stream_with_scy(
series: u64, series: u64,
chn: &ChannelTyped, chn: &ChannelTyped,
coord: &PreBinnedPatchCoord, coord: &PreBinnedPatchCoord,
agg_kind: AggKind, one_before_range: bool,
transform: Transform,
cache_usage: CacheUsage, cache_usage: CacheUsage,
scy: Arc<ScySession>, scy: Arc<ScySession>,
) -> Result<(Box<dyn TimeBinned>, bool), Error> { ) -> Result<(Box<dyn TimeBinned>, bool), Error> {
trace!("pre_binned_value_stream_with_scy {chn:?} {coord:?}"); trace!("pre_binned_value_stream_with_scy {chn:?} {coord:?}");
if let (Some(item), CacheUsage::Use) = ( if let (Some(item), CacheUsage::Use) = (read_cached_scylla(series, chn, coord, &scy).await?, &cache_usage) {
read_cached_scylla(series, chn, coord, agg_kind.clone(), &scy).await?,
&cache_usage,
) {
info!("+++++++++++++ GOOD READ"); info!("+++++++++++++ GOOD READ");
Ok((item, true)) Ok((item, true))
} else { } else {
if let CacheUsage::Use = &cache_usage { if let CacheUsage::Use = &cache_usage {
warn!("--+--+--+--+--+--+ NOT YET CACHED"); warn!("--+--+--+--+--+--+ NOT YET CACHED");
} }
let res = fetch_uncached_data_box(series, chn, coord, agg_kind, cache_usage, scy).await?; let res = fetch_uncached_data_box(series, chn, coord, one_before_range, transform, cache_usage, scy).await?;
let (bin, complete) = let (bin, complete) =
res.ok_or_else(|| Error::with_msg_no_trace(format!("pre_binned_value_stream_with_scy got None bin")))?; res.ok_or_else(|| Error::with_msg_no_trace(format!("pre_binned_value_stream_with_scy got None bin")))?;
Ok((bin, complete)) Ok((bin, complete))
@@ -497,7 +496,8 @@ pub async fn pre_binned_value_stream(
scy: Arc<ScySession>, scy: Arc<ScySession>,
) -> Result<Pin<Box<dyn Stream<Item = Result<Box<dyn TimeBinned>, Error>> + Send>>, Error> { ) -> Result<Pin<Box<dyn Stream<Item = Result<Box<dyn TimeBinned>, Error>> + Send>>, Error> {
trace!("pre_binned_value_stream series {series} {chn:?} {coord:?}"); trace!("pre_binned_value_stream series {series} {chn:?} {coord:?}");
let res = pre_binned_value_stream_with_scy(series, chn, coord, agg_kind, cache_usage, scy).await?; let res =
pre_binned_value_stream_with_scy(series, chn, coord, one_before_range, transform, cache_usage, scy).await?;
error!("TODO pre_binned_value_stream"); error!("TODO pre_binned_value_stream");
err::todo(); err::todo();
Ok(Box::pin(futures_util::stream::iter([Ok(res.0)]))) Ok(Box::pin(futures_util::stream::iter([Ok(res.0)])))
+7 -7
View File
@@ -1,4 +1,5 @@
use crate::errconv::ErrConv; use crate::errconv::ErrConv;
use crate::ScyllaSeriesRange;
use err::Error; use err::Error;
use futures_util::Future; use futures_util::Future;
use futures_util::FutureExt; use futures_util::FutureExt;
@@ -12,7 +13,6 @@ use items_2::channelevents::ChannelEvents;
use items_2::eventsdim0::EventsDim0; use items_2::eventsdim0::EventsDim0;
use items_2::eventsdim1::EventsDim1; use items_2::eventsdim1::EventsDim1;
use netpod::log::*; use netpod::log::*;
use netpod::NanoRange;
use netpod::ScalarType; use netpod::ScalarType;
use netpod::Shape; use netpod::Shape;
use scylla::Session as ScySession; use scylla::Session as ScySession;
@@ -25,7 +25,7 @@ use std::task::Poll;
async fn find_ts_msp( async fn find_ts_msp(
series: u64, series: u64,
range: NanoRange, range: ScyllaSeriesRange,
scy: Arc<ScySession>, scy: Arc<ScySession>,
) -> Result<(VecDeque<u64>, VecDeque<u64>), Error> { ) -> Result<(VecDeque<u64>, VecDeque<u64>), Error> {
trace!("find_ts_msp series {} {:?}", series, range); trace!("find_ts_msp series {} {:?}", series, range);
@@ -131,7 +131,7 @@ impl_scaty_array!(Vec<bool>, bool, Vec<bool>, "events_array_bool");
struct ReadNextValuesOpts { struct ReadNextValuesOpts {
series: u64, series: u64,
ts_msp: u64, ts_msp: u64,
range: NanoRange, range: ScyllaSeriesRange,
fwd: bool, fwd: bool,
with_values: bool, with_values: bool,
scy: Arc<ScySession>, scy: Arc<ScySession>,
@@ -277,7 +277,7 @@ struct ReadValues {
series: u64, series: u64,
scalar_type: ScalarType, scalar_type: ScalarType,
shape: Shape, shape: Shape,
range: NanoRange, range: ScyllaSeriesRange,
ts_msps: VecDeque<u64>, ts_msps: VecDeque<u64>,
fwd: bool, fwd: bool,
with_values: bool, with_values: bool,
@@ -291,7 +291,7 @@ impl ReadValues {
series: u64, series: u64,
scalar_type: ScalarType, scalar_type: ScalarType,
shape: Shape, shape: Shape,
range: NanoRange, range: ScyllaSeriesRange,
ts_msps: VecDeque<u64>, ts_msps: VecDeque<u64>,
fwd: bool, fwd: bool,
with_values: bool, with_values: bool,
@@ -397,7 +397,7 @@ pub struct EventsStreamScylla {
series: u64, series: u64,
scalar_type: ScalarType, scalar_type: ScalarType,
shape: Shape, shape: Shape,
range: NanoRange, range: ScyllaSeriesRange,
do_one_before_range: bool, do_one_before_range: bool,
ts_msp_bck: VecDeque<u64>, ts_msp_bck: VecDeque<u64>,
ts_msp_fwd: VecDeque<u64>, ts_msp_fwd: VecDeque<u64>,
@@ -411,7 +411,7 @@ pub struct EventsStreamScylla {
impl EventsStreamScylla { impl EventsStreamScylla {
pub fn new( pub fn new(
series: u64, series: u64,
range: NanoRange, range: ScyllaSeriesRange,
do_one_before_range: bool, do_one_before_range: bool,
scalar_type: ScalarType, scalar_type: ScalarType,
shape: Shape, shape: Shape,
+6
View File
@@ -11,6 +11,12 @@ use scylla::statement::Consistency;
use scylla::Session as ScySession; use scylla::Session as ScySession;
use std::sync::Arc; use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct ScyllaSeriesRange {
beg: u64,
end: u64,
}
pub async fn create_scy_session(scyconf: &ScyllaConfig) -> Result<Arc<ScySession>, Error> { pub async fn create_scy_session(scyconf: &ScyllaConfig) -> Result<Arc<ScySession>, Error> {
let scy = scylla::SessionBuilder::new() let scy = scylla::SessionBuilder::new()
.known_nodes(&scyconf.hosts) .known_nodes(&scyconf.hosts)