Read back array data from value blob
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
use crate::errconv::ErrConv;
|
||||
use crate::events::EventsStreamScylla;
|
||||
use err::Error;
|
||||
use futures_util::Future;
|
||||
use futures_util::Stream;
|
||||
|
||||
+236
-104
@@ -1,5 +1,6 @@
|
||||
use crate::errconv::ErrConv;
|
||||
use crate::range::ScyllaSeriesRange;
|
||||
use crate::worker::ScyllaQueue;
|
||||
use err::Error;
|
||||
use futures_util::Future;
|
||||
use futures_util::FutureExt;
|
||||
@@ -20,7 +21,10 @@ use netpod::Shape;
|
||||
use netpod::TsMs;
|
||||
use netpod::TsNano;
|
||||
use scylla::frame::response::result::Row;
|
||||
use scylla::prepared_statement::PreparedStatement;
|
||||
use scylla::Session;
|
||||
use scylla::Session as ScySession;
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::VecDeque;
|
||||
use std::mem;
|
||||
use std::pin::Pin;
|
||||
@@ -28,61 +32,131 @@ use std::sync::Arc;
|
||||
use std::task::Context;
|
||||
use std::task::Poll;
|
||||
|
||||
async fn find_ts_msp(
|
||||
#[derive(Debug)]
|
||||
pub struct StmtsEventsRt {
|
||||
ts_msp_bck: PreparedStatement,
|
||||
ts_msp_fwd: PreparedStatement,
|
||||
read_value_queries: BTreeMap<String, PreparedStatement>,
|
||||
}
|
||||
|
||||
impl StmtsEventsRt {
|
||||
pub(super) async fn new(rtpre: &str, scy: &Session) -> Result<Self, Error> {
|
||||
let cql = format!(
|
||||
"select ts_msp from {}{} where series = ? and ts_msp < ? order by ts_msp desc limit 2",
|
||||
rtpre, "ts_msp"
|
||||
);
|
||||
let ts_msp_bck = scy.prepare(cql).await.err_conv()?;
|
||||
let cql = format!(
|
||||
"select ts_msp from {}{} where series = ? and ts_msp >= ? and ts_msp < ?",
|
||||
rtpre, "ts_msp"
|
||||
);
|
||||
let ts_msp_fwd = scy.prepare(cql).await.err_conv()?;
|
||||
let mut read_value_queries = BTreeMap::new();
|
||||
for sct in [
|
||||
"u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "string",
|
||||
] {
|
||||
let combinations = [
|
||||
("timestamps", "scalar", "ts_lsp, pulse"),
|
||||
("timestamps", "array", "ts_lsp, pulse"),
|
||||
("values", "scalar", "ts_lsp, pulse, value"),
|
||||
("valueblobs", "array", "ts_lsp, pulse, valueblob"),
|
||||
];
|
||||
for com in combinations {
|
||||
let query_name = format!("{}_{}_{}_fwd", com.1, sct, com.0);
|
||||
let cql = format!(
|
||||
concat!(
|
||||
"select {} from {}events_{}_{}",
|
||||
" where series = ? and ts_msp = ? and ts_lsp >= ? and ts_lsp < ?"
|
||||
),
|
||||
com.2, rtpre, com.1, sct,
|
||||
);
|
||||
let qu = scy.prepare(cql).await.err_conv()?;
|
||||
read_value_queries.insert(query_name, qu);
|
||||
|
||||
let query_name = format!("{}_{}_{}_bck", com.1, sct, com.0);
|
||||
let cql = format!(
|
||||
concat!(
|
||||
"select {} from {}events_{}_{}",
|
||||
" where series = ? and ts_msp = ? and ts_lsp < ? order by ts_lsp desc limit 1"
|
||||
),
|
||||
com.2, rtpre, com.1, sct,
|
||||
);
|
||||
let qu = scy.prepare(cql).await.err_conv()?;
|
||||
read_value_queries.insert(query_name, qu);
|
||||
}
|
||||
}
|
||||
let ret = Self {
|
||||
ts_msp_bck,
|
||||
ts_msp_fwd,
|
||||
read_value_queries,
|
||||
};
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) async fn find_ts_msp_worker(
|
||||
series: u64,
|
||||
range: ScyllaSeriesRange,
|
||||
scy: Arc<ScySession>,
|
||||
stmts: &StmtsEventsRt,
|
||||
scy: &ScySession,
|
||||
) -> Result<(VecDeque<TsMs>, VecDeque<TsMs>), Error> {
|
||||
trace!("find_ts_msp series {:?} {:?}", series, range);
|
||||
let mut ret1 = VecDeque::new();
|
||||
let mut ret2 = VecDeque::new();
|
||||
// TODO use prepared statements
|
||||
let cql = "select ts_msp from st_ts_msp where series = ? and ts_msp < ? order by ts_msp desc limit 2";
|
||||
let params = (series as i64, range.beg().ms() as i64);
|
||||
trace!("find_ts_msp query 1 params {:?}", params);
|
||||
let res = scy.query(cql, params).await.err_conv()?;
|
||||
for row in res.rows_typed_or_empty::<(i64,)>() {
|
||||
let row = row.err_conv()?;
|
||||
let mut res = scy
|
||||
.execute_iter(stmts.ts_msp_bck.clone(), params)
|
||||
.await
|
||||
.err_conv()?
|
||||
.into_typed::<(i64,)>();
|
||||
while let Some(x) = res.next().await {
|
||||
let row = x.map_err(|e| Error::with_msg_no_trace(e.to_string()))?;
|
||||
let ts = TsMs::from_ms_u64(row.0 as u64);
|
||||
trace!("query 1 ts_msp {}", ts);
|
||||
ret1.push_front(ts);
|
||||
}
|
||||
let cql = "select ts_msp from st_ts_msp where series = ? and ts_msp >= ? and ts_msp < ?";
|
||||
let params = (series as i64, range.beg().ms() as i64, 1 + range.end().ms() as i64);
|
||||
trace!("find_ts_msp query 2 params {:?}", params);
|
||||
let res = scy.query(cql, params).await.err_conv()?;
|
||||
for row in res.rows_typed_or_empty::<(i64,)>() {
|
||||
let row = row.err_conv()?;
|
||||
let mut res = scy
|
||||
.execute_iter(stmts.ts_msp_fwd.clone(), params)
|
||||
.await
|
||||
.err_conv()?
|
||||
.into_typed::<(i64,)>();
|
||||
while let Some(x) = res.next().await {
|
||||
let row = x.map_err(|e| Error::with_msg_no_trace(e.to_string()))?;
|
||||
let ts = TsMs::from_ms_u64(row.0 as u64);
|
||||
trace!("query 2 ts_msp {}", ts);
|
||||
ret2.push_back(ts);
|
||||
}
|
||||
let cql = "select ts_msp from st_ts_msp where series = ? and ts_msp >= ? limit 1";
|
||||
let params = (series as i64, range.end().ms() as i64);
|
||||
trace!("find_ts_msp query 3 params {:?}", params);
|
||||
let res = scy.query(cql, params).await.err_conv()?;
|
||||
for row in res.rows_typed_or_empty::<(i64,)>() {
|
||||
let row = row.err_conv()?;
|
||||
let ts = TsMs::from_ms_u64(row.0 as u64);
|
||||
trace!("query 3 ts_msp {}", ts);
|
||||
ret2.push_back(ts);
|
||||
ret2.push_front(ts);
|
||||
}
|
||||
// let cql = "select ts_msp from st_ts_msp where series = ? and ts_msp >= ? limit 1";
|
||||
// let params = (series as i64, range.end().ms() as i64);
|
||||
// trace!("find_ts_msp query 3 params {:?}", params);
|
||||
// let res = scy.query(cql, params).await.err_conv()?;
|
||||
// for row in res.rows_typed_or_empty::<(i64,)>() {
|
||||
// let row = row.err_conv()?;
|
||||
// let ts = TsMs::from_ms_u64(row.0 as u64);
|
||||
// trace!("query 3 ts_msp {}", ts);
|
||||
// ret2.push_back(ts);
|
||||
// }
|
||||
trace!("find_ts_msp n1 {:?} n2 {:?}", ret1.len(), ret2.len());
|
||||
Ok((ret1, ret2))
|
||||
}
|
||||
|
||||
trait ValTy: Sized {
|
||||
trait ValTy: Sized + 'static {
|
||||
type ScaTy: ScalarOps + std::default::Default;
|
||||
type ScyTy: scylla::cql_to_rust::FromCqlVal<scylla::frame::response::result::CqlValue>;
|
||||
type Container: Events + Appendable<Self>;
|
||||
fn from_scyty(inp: Self::ScyTy) -> Self;
|
||||
fn from_valueblob(inp: Vec<u8>) -> Self;
|
||||
fn table_name() -> &'static str;
|
||||
fn default() -> Self;
|
||||
fn is_valueblob() -> bool;
|
||||
fn st_name() -> &'static str;
|
||||
}
|
||||
|
||||
macro_rules! impl_scaty_scalar {
|
||||
($st:ty, $st_scy:ty, $table_name:expr) => {
|
||||
($st:ty, $st_scy:ty, $st_name:expr, $table_name:expr) => {
|
||||
impl ValTy for $st {
|
||||
type ScaTy = $st;
|
||||
type ScyTy = $st_scy;
|
||||
@@ -90,6 +164,9 @@ macro_rules! impl_scaty_scalar {
|
||||
fn from_scyty(inp: Self::ScyTy) -> Self {
|
||||
inp as Self
|
||||
}
|
||||
fn from_valueblob(_inp: Vec<u8>) -> Self {
|
||||
<Self as ValTy>::default()
|
||||
}
|
||||
fn table_name() -> &'static str {
|
||||
$table_name
|
||||
}
|
||||
@@ -99,12 +176,15 @@ macro_rules! impl_scaty_scalar {
|
||||
fn is_valueblob() -> bool {
|
||||
false
|
||||
}
|
||||
fn st_name() -> &'static str {
|
||||
$st_name
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_scaty_array {
|
||||
($vt:ty, $st:ty, $st_scy:ty, $table_name:expr) => {
|
||||
($vt:ty, $st:ty, $st_scy:ty, $st_name:expr, $table_name:expr) => {
|
||||
impl ValTy for $vt {
|
||||
type ScaTy = $st;
|
||||
type ScyTy = $st_scy;
|
||||
@@ -112,6 +192,22 @@ macro_rules! impl_scaty_array {
|
||||
fn from_scyty(inp: Self::ScyTy) -> Self {
|
||||
inp.into_iter().map(|x| x as Self::ScaTy).collect()
|
||||
}
|
||||
fn from_valueblob(inp: Vec<u8>) -> Self {
|
||||
if inp.len() < 32 {
|
||||
<Self as ValTy>::default()
|
||||
} else {
|
||||
let en = std::mem::size_of::<Self::ScaTy>();
|
||||
let n = (inp.len().max(32) - 32) / en;
|
||||
let mut c = Vec::with_capacity(n);
|
||||
for i in 0..n {
|
||||
let r1 = &inp[32 + en * (0 + i)..32 + en * (1 + i)];
|
||||
let p1 = r1 as *const _ as *const $st;
|
||||
let v1 = unsafe { p1.read_unaligned() };
|
||||
c.push(v1);
|
||||
}
|
||||
c
|
||||
}
|
||||
}
|
||||
fn table_name() -> &'static str {
|
||||
$table_name
|
||||
}
|
||||
@@ -121,35 +217,38 @@ macro_rules! impl_scaty_array {
|
||||
fn is_valueblob() -> bool {
|
||||
true
|
||||
}
|
||||
fn st_name() -> &'static str {
|
||||
$st_name
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_scaty_scalar!(u8, i8, "st_events_scalar_u8");
|
||||
impl_scaty_scalar!(u16, i16, "st_events_scalar_u16");
|
||||
impl_scaty_scalar!(u32, i32, "st_events_scalar_u32");
|
||||
impl_scaty_scalar!(u64, i64, "st_events_scalar_u64");
|
||||
impl_scaty_scalar!(i8, i8, "st_events_scalar_i8");
|
||||
impl_scaty_scalar!(i16, i16, "st_events_scalar_i16");
|
||||
impl_scaty_scalar!(i32, i32, "st_events_scalar_i32");
|
||||
impl_scaty_scalar!(i64, i64, "st_events_scalar_i64");
|
||||
impl_scaty_scalar!(f32, f32, "st_events_scalar_f32");
|
||||
impl_scaty_scalar!(f64, f64, "st_events_scalar_f64");
|
||||
impl_scaty_scalar!(bool, bool, "st_events_scalar_bool");
|
||||
impl_scaty_scalar!(String, String, "st_events_scalar_string");
|
||||
impl_scaty_scalar!(u8, i8, "u8", "st_events_scalar_u8");
|
||||
impl_scaty_scalar!(u16, i16, "u16", "st_events_scalar_u16");
|
||||
impl_scaty_scalar!(u32, i32, "u32", "st_events_scalar_u32");
|
||||
impl_scaty_scalar!(u64, i64, "u64", "st_events_scalar_u64");
|
||||
impl_scaty_scalar!(i8, i8, "i8", "st_events_scalar_i8");
|
||||
impl_scaty_scalar!(i16, i16, "i16", "st_events_scalar_i16");
|
||||
impl_scaty_scalar!(i32, i32, "i32", "st_events_scalar_i32");
|
||||
impl_scaty_scalar!(i64, i64, "i64", "st_events_scalar_i64");
|
||||
impl_scaty_scalar!(f32, f32, "f32", "st_events_scalar_f32");
|
||||
impl_scaty_scalar!(f64, f64, "f64", "st_events_scalar_f64");
|
||||
impl_scaty_scalar!(bool, bool, "bool", "st_events_scalar_bool");
|
||||
impl_scaty_scalar!(String, String, "string", "st_events_scalar_string");
|
||||
|
||||
impl_scaty_array!(Vec<u8>, u8, Vec<i8>, "st_events_array_u8");
|
||||
impl_scaty_array!(Vec<u16>, u16, Vec<i16>, "st_events_array_u16");
|
||||
impl_scaty_array!(Vec<u32>, u32, Vec<i32>, "st_events_array_u32");
|
||||
impl_scaty_array!(Vec<u64>, u64, Vec<i64>, "st_events_array_u64");
|
||||
impl_scaty_array!(Vec<i8>, i8, Vec<i8>, "st_events_array_i8");
|
||||
impl_scaty_array!(Vec<i16>, i16, Vec<i16>, "st_events_array_i16");
|
||||
impl_scaty_array!(Vec<i32>, i32, Vec<i32>, "st_events_array_i32");
|
||||
impl_scaty_array!(Vec<i64>, i64, Vec<i64>, "st_events_array_i64");
|
||||
impl_scaty_array!(Vec<f32>, f32, Vec<f32>, "st_events_array_f32");
|
||||
impl_scaty_array!(Vec<f64>, f64, Vec<f64>, "st_events_array_f64");
|
||||
impl_scaty_array!(Vec<bool>, bool, Vec<bool>, "st_events_array_bool");
|
||||
impl_scaty_array!(Vec<String>, String, Vec<String>, "st_events_array_string");
|
||||
impl_scaty_array!(Vec<u8>, u8, Vec<i8>, "u8", "st_events_array_u8");
|
||||
impl_scaty_array!(Vec<u16>, u16, Vec<i16>, "u16", "st_events_array_u16");
|
||||
impl_scaty_array!(Vec<u32>, u32, Vec<i32>, "u32", "st_events_array_u32");
|
||||
impl_scaty_array!(Vec<u64>, u64, Vec<i64>, "u64", "st_events_array_u64");
|
||||
impl_scaty_array!(Vec<i8>, i8, Vec<i8>, "i8", "st_events_array_i8");
|
||||
impl_scaty_array!(Vec<i16>, i16, Vec<i16>, "i16", "st_events_array_i16");
|
||||
impl_scaty_array!(Vec<i32>, i32, Vec<i32>, "i32", "st_events_array_i32");
|
||||
impl_scaty_array!(Vec<i64>, i64, Vec<i64>, "i64", "st_events_array_i64");
|
||||
impl_scaty_array!(Vec<f32>, f32, Vec<f32>, "f32", "st_events_array_f32");
|
||||
impl_scaty_array!(Vec<f64>, f64, Vec<f64>, "f64", "st_events_array_f64");
|
||||
impl_scaty_array!(Vec<bool>, bool, Vec<bool>, "bool", "st_events_array_bool");
|
||||
// impl_scaty_array!(Vec<String>, String, Vec<String>, "string", "st_events_array_string");
|
||||
|
||||
struct ReadNextValuesOpts {
|
||||
series: u64,
|
||||
@@ -157,33 +256,40 @@ struct ReadNextValuesOpts {
|
||||
range: ScyllaSeriesRange,
|
||||
fwd: bool,
|
||||
with_values: bool,
|
||||
scy: Arc<ScySession>,
|
||||
scyqueue: ScyllaQueue,
|
||||
}
|
||||
|
||||
async fn read_next_values<ST>(opts: ReadNextValuesOpts) -> Result<Box<dyn Events>, Error>
|
||||
where
|
||||
ST: ValTy,
|
||||
{
|
||||
debug!("read_next_values {} {}", opts.series, opts.ts_msp);
|
||||
// TODO could take scyqeue out of opts struct.
|
||||
let scyqueue = opts.scyqueue.clone();
|
||||
let futgen = Box::new(|scy: Arc<ScySession>, stmts: Arc<StmtsEventsRt>| {
|
||||
let fut = read_next_values_worker::<ST>(opts, scy, stmts);
|
||||
Box::pin(fut) as Pin<Box<dyn Future<Output = Result<Box<dyn Events>, err::Error>> + Send>>
|
||||
});
|
||||
let res = scyqueue.read_next_values(futgen).await?;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
async fn read_next_values_worker<ST>(
|
||||
opts: ReadNextValuesOpts,
|
||||
scy: Arc<ScySession>,
|
||||
stmts: Arc<StmtsEventsRt>,
|
||||
) -> Result<Box<dyn Events>, Error>
|
||||
where
|
||||
ST: ValTy,
|
||||
{
|
||||
trace!("read_next_values_worker {} {}", opts.series, opts.ts_msp);
|
||||
let series = opts.series;
|
||||
let ts_msp = opts.ts_msp;
|
||||
let range = opts.range;
|
||||
let fwd = opts.fwd;
|
||||
let scy = opts.scy;
|
||||
let table_name = ST::table_name();
|
||||
if range.end() > TsNano::from_ns(i64::MAX as u64) {
|
||||
return Err(Error::with_msg_no_trace(format!("range.end overflows i64")));
|
||||
}
|
||||
let cql_fields = if opts.with_values {
|
||||
if ST::is_valueblob() {
|
||||
"ts_lsp, pulse, valueblob"
|
||||
} else {
|
||||
"ts_lsp, pulse, value"
|
||||
}
|
||||
} else {
|
||||
"ts_lsp, pulse"
|
||||
};
|
||||
let ret = if fwd {
|
||||
let ret = if opts.fwd {
|
||||
let ts_lsp_min = if range.beg() > ts_msp.ns() {
|
||||
range.beg().delta(ts_msp.ns())
|
||||
} else {
|
||||
@@ -201,14 +307,20 @@ where
|
||||
ts_lsp_max,
|
||||
table_name,
|
||||
);
|
||||
// TODO use prepared!
|
||||
let cql = format!(
|
||||
concat!(
|
||||
"select {} from {}",
|
||||
" where series = ? and ts_msp = ? and ts_lsp >= ? and ts_lsp < ?"
|
||||
),
|
||||
cql_fields, table_name,
|
||||
);
|
||||
let qu_name = if opts.with_values {
|
||||
if ST::is_valueblob() {
|
||||
format!("array_{}_valueblobs_fwd", ST::st_name())
|
||||
} else {
|
||||
format!("array_{}_values_fwd", ST::st_name())
|
||||
}
|
||||
} else {
|
||||
format!("array_{}_timestamps_fwd", ST::st_name())
|
||||
};
|
||||
let qu = stmts.read_value_queries.get(&qu_name).ok_or_else(|| {
|
||||
let e = Error::with_msg_no_trace(format!("can not find query name {}", qu_name));
|
||||
error!("{e}");
|
||||
e
|
||||
})?;
|
||||
let params = (
|
||||
series as i64,
|
||||
ts_msp.ms() as i64,
|
||||
@@ -216,13 +328,13 @@ where
|
||||
ts_lsp_max.ns() as i64,
|
||||
);
|
||||
trace!("FWD event search params {:?}", params);
|
||||
let mut res = scy.query_iter(cql, params).await.err_conv()?;
|
||||
let mut res = scy.execute_iter(qu.clone(), params).await.err_conv()?;
|
||||
let mut rows = Vec::new();
|
||||
while let Some(x) = res.next().await {
|
||||
rows.push(x.err_conv()?);
|
||||
}
|
||||
let mut last_before = None;
|
||||
let ret = convert_rows::<ST>(rows, range, ts_msp, opts.with_values, !fwd, &mut last_before)?;
|
||||
let ret = convert_rows::<ST>(rows, range, ts_msp, opts.with_values, !opts.fwd, &mut last_before)?;
|
||||
ret
|
||||
} else {
|
||||
let ts_lsp_max = if ts_msp.ns() < range.beg() {
|
||||
@@ -231,23 +343,29 @@ where
|
||||
DtNano::from_ns(0)
|
||||
};
|
||||
trace!("BCK ts_msp {} ts_lsp_max {} {}", ts_msp, ts_lsp_max, table_name,);
|
||||
// TODO use prepared!
|
||||
let cql = format!(
|
||||
concat!(
|
||||
"select {} from {}",
|
||||
" where series = ? and ts_msp = ? and ts_lsp < ? order by ts_lsp desc limit 1"
|
||||
),
|
||||
cql_fields, table_name,
|
||||
);
|
||||
let qu_name = if opts.with_values {
|
||||
if ST::is_valueblob() {
|
||||
format!("array_{}_valueblobs_bck", ST::st_name())
|
||||
} else {
|
||||
format!("array_{}_values_bck", ST::st_name())
|
||||
}
|
||||
} else {
|
||||
format!("array_{}_timestamps_bck", ST::st_name())
|
||||
};
|
||||
let qu = stmts.read_value_queries.get(&qu_name).ok_or_else(|| {
|
||||
let e = Error::with_msg_no_trace(format!("can not find query name {}", qu_name));
|
||||
error!("{e}");
|
||||
e
|
||||
})?;
|
||||
let params = (series as i64, ts_msp.ms() as i64, ts_lsp_max.ns() as i64);
|
||||
trace!("BCK event search params {:?}", params);
|
||||
let mut res = scy.query_iter(cql, params).await.err_conv()?;
|
||||
let mut res = scy.execute_iter(qu.clone(), params).await.err_conv()?;
|
||||
let mut rows = Vec::new();
|
||||
while let Some(x) = res.next().await {
|
||||
rows.push(x.err_conv()?);
|
||||
}
|
||||
let mut _last_before = None;
|
||||
let ret = convert_rows::<ST>(rows, range, ts_msp, opts.with_values, !fwd, &mut _last_before)?;
|
||||
let ret = convert_rows::<ST>(rows, range, ts_msp, opts.with_values, !opts.fwd, &mut _last_before)?;
|
||||
if ret.len() > 1 {
|
||||
error!("multiple events in backwards search {}", ret.len());
|
||||
}
|
||||
@@ -274,7 +392,7 @@ fn convert_rows<ST: ValTy>(
|
||||
trace!("read a value blob len {}", row.2.len());
|
||||
let ts = TsNano::from_ns(ts_msp.ns_u64() + row.0 as u64);
|
||||
let pulse = row.1 as u64;
|
||||
let value = ValTy::default();
|
||||
let value = ValTy::from_valueblob(row.2);
|
||||
(ts, pulse, value)
|
||||
} else {
|
||||
let row: (i64, i64, ST::ScyTy) = row.into_typed().err_conv()?;
|
||||
@@ -326,7 +444,7 @@ struct ReadValues {
|
||||
with_values: bool,
|
||||
fut: Pin<Box<dyn Future<Output = Result<Box<dyn Events>, Error>> + Send>>,
|
||||
fut_done: bool,
|
||||
scy: Arc<ScySession>,
|
||||
scyqueue: ScyllaQueue,
|
||||
}
|
||||
|
||||
impl ReadValues {
|
||||
@@ -338,7 +456,7 @@ impl ReadValues {
|
||||
ts_msps: VecDeque<TsMs>,
|
||||
fwd: bool,
|
||||
with_values: bool,
|
||||
scy: Arc<ScySession>,
|
||||
scyqueue: ScyllaQueue,
|
||||
) -> Self {
|
||||
let mut ret = Self {
|
||||
series,
|
||||
@@ -352,7 +470,7 @@ impl ReadValues {
|
||||
"future not initialized",
|
||||
)))),
|
||||
fut_done: false,
|
||||
scy,
|
||||
scyqueue,
|
||||
};
|
||||
ret.next();
|
||||
ret
|
||||
@@ -375,7 +493,7 @@ impl ReadValues {
|
||||
range: self.range.clone(),
|
||||
fwd: self.fwd,
|
||||
with_values: self.with_values,
|
||||
scy: self.scy.clone(),
|
||||
scyqueue: self.scyqueue.clone(),
|
||||
};
|
||||
let scalar_type = self.scalar_type.clone();
|
||||
let shape = self.shape.clone();
|
||||
@@ -394,8 +512,8 @@ impl ReadValues {
|
||||
ScalarType::F64 => read_next_values::<f64>(opts).await,
|
||||
ScalarType::BOOL => read_next_values::<bool>(opts).await,
|
||||
ScalarType::STRING => read_next_values::<String>(opts).await,
|
||||
_ => {
|
||||
error!("TODO ReadValues add more types");
|
||||
ScalarType::ChannelStatus => {
|
||||
warn!("read scalar channel status not yet supported");
|
||||
err::todoval()
|
||||
}
|
||||
},
|
||||
@@ -411,8 +529,12 @@ impl ReadValues {
|
||||
ScalarType::F32 => read_next_values::<Vec<f32>>(opts).await,
|
||||
ScalarType::F64 => read_next_values::<Vec<f64>>(opts).await,
|
||||
ScalarType::BOOL => read_next_values::<Vec<bool>>(opts).await,
|
||||
_ => {
|
||||
error!("TODO ReadValues add more types");
|
||||
ScalarType::STRING => {
|
||||
warn!("read array string not yet supported");
|
||||
err::todoval()
|
||||
}
|
||||
ScalarType::ChannelStatus => {
|
||||
warn!("read array channel status not yet supported");
|
||||
err::todoval()
|
||||
}
|
||||
},
|
||||
@@ -428,7 +550,7 @@ impl ReadValues {
|
||||
|
||||
enum FrState {
|
||||
New,
|
||||
FindMsp(Pin<Box<dyn Future<Output = Result<(VecDeque<TsMs>, VecDeque<TsMs>), Error>> + Send>>),
|
||||
FindMsp(Pin<Box<dyn Future<Output = Result<(VecDeque<TsMs>, VecDeque<TsMs>), crate::worker::Error>> + Send>>),
|
||||
ReadBack1(ReadValues),
|
||||
ReadBack2(ReadValues),
|
||||
ReadValues(ReadValues),
|
||||
@@ -445,7 +567,7 @@ pub struct EventsStreamScylla {
|
||||
do_one_before_range: bool,
|
||||
ts_msp_bck: VecDeque<TsMs>,
|
||||
ts_msp_fwd: VecDeque<TsMs>,
|
||||
scy: Arc<ScySession>,
|
||||
scyqueue: ScyllaQueue,
|
||||
do_test_stream_error: bool,
|
||||
found_one_after: bool,
|
||||
with_values: bool,
|
||||
@@ -460,7 +582,7 @@ impl EventsStreamScylla {
|
||||
scalar_type: ScalarType,
|
||||
shape: Shape,
|
||||
with_values: bool,
|
||||
scy: Arc<ScySession>,
|
||||
scyqueue: ScyllaQueue,
|
||||
do_test_stream_error: bool,
|
||||
) -> Self {
|
||||
debug!("EventsStreamScylla::new");
|
||||
@@ -473,7 +595,7 @@ impl EventsStreamScylla {
|
||||
do_one_before_range,
|
||||
ts_msp_bck: VecDeque::new(),
|
||||
ts_msp_fwd: VecDeque::new(),
|
||||
scy,
|
||||
scyqueue,
|
||||
do_test_stream_error,
|
||||
found_one_after: false,
|
||||
with_values,
|
||||
@@ -505,7 +627,7 @@ impl EventsStreamScylla {
|
||||
[msp].into(),
|
||||
false,
|
||||
self.with_values,
|
||||
self.scy.clone(),
|
||||
self.scyqueue.clone(),
|
||||
);
|
||||
self.state = FrState::ReadBack1(st);
|
||||
} else if self.ts_msp_fwd.len() > 0 {
|
||||
@@ -518,7 +640,7 @@ impl EventsStreamScylla {
|
||||
mem::replace(&mut self.ts_msp_fwd, VecDeque::new()),
|
||||
true,
|
||||
self.with_values,
|
||||
self.scy.clone(),
|
||||
self.scyqueue.clone(),
|
||||
);
|
||||
self.state = FrState::ReadValues(st);
|
||||
} else {
|
||||
@@ -539,7 +661,7 @@ impl EventsStreamScylla {
|
||||
mem::replace(&mut self.ts_msp_fwd, VecDeque::new()),
|
||||
true,
|
||||
self.with_values,
|
||||
self.scy.clone(),
|
||||
self.scyqueue.clone(),
|
||||
);
|
||||
self.state = FrState::ReadValues(st);
|
||||
} else {
|
||||
@@ -556,7 +678,7 @@ impl EventsStreamScylla {
|
||||
[msp].into(),
|
||||
false,
|
||||
self.with_values,
|
||||
self.scy.clone(),
|
||||
self.scyqueue.clone(),
|
||||
);
|
||||
self.state = FrState::ReadBack2(st);
|
||||
} else if self.ts_msp_fwd.len() > 0 {
|
||||
@@ -569,7 +691,7 @@ impl EventsStreamScylla {
|
||||
mem::replace(&mut self.ts_msp_fwd, VecDeque::new()),
|
||||
true,
|
||||
self.with_values,
|
||||
self.scy.clone(),
|
||||
self.scyqueue.clone(),
|
||||
);
|
||||
self.state = FrState::ReadValues(st);
|
||||
} else {
|
||||
@@ -593,7 +715,7 @@ impl EventsStreamScylla {
|
||||
mem::replace(&mut self.ts_msp_fwd, VecDeque::new()),
|
||||
true,
|
||||
self.with_values,
|
||||
self.scy.clone(),
|
||||
self.scyqueue.clone(),
|
||||
);
|
||||
self.state = FrState::ReadValues(st);
|
||||
} else {
|
||||
@@ -602,6 +724,14 @@ impl EventsStreamScylla {
|
||||
}
|
||||
}
|
||||
|
||||
async fn find_ts_msp_via_queue(
|
||||
series: u64,
|
||||
range: ScyllaSeriesRange,
|
||||
scyqueue: ScyllaQueue,
|
||||
) -> Result<(VecDeque<TsMs>, VecDeque<TsMs>), crate::worker::Error> {
|
||||
scyqueue.find_ts_msp(series, range).await
|
||||
}
|
||||
|
||||
impl Stream for EventsStreamScylla {
|
||||
type Item = Result<ChannelEvents, Error>;
|
||||
|
||||
@@ -620,7 +750,9 @@ impl Stream for EventsStreamScylla {
|
||||
}
|
||||
break match self.state {
|
||||
FrState::New => {
|
||||
let fut = find_ts_msp(self.series, self.range.clone(), self.scy.clone());
|
||||
let series = self.series.clone();
|
||||
let range = self.range.clone();
|
||||
let fut = find_ts_msp_via_queue(series, range, self.scyqueue.clone());
|
||||
let fut = Box::pin(fut);
|
||||
self.state = FrState::FindMsp(fut);
|
||||
continue;
|
||||
@@ -633,7 +765,7 @@ impl Stream for EventsStreamScylla {
|
||||
Ready(Err(e)) => {
|
||||
error!("EventsStreamScylla FindMsp {e}");
|
||||
self.state = FrState::DataDone;
|
||||
Ready(Some(Err(e)))
|
||||
Ready(Some(Err(e.into())))
|
||||
}
|
||||
Pending => Pending,
|
||||
},
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
use crate::conn::create_scy_session_no_ks;
|
||||
use crate::events::StmtsEventsRt;
|
||||
use crate::range::ScyllaSeriesRange;
|
||||
use async_channel::Receiver;
|
||||
use async_channel::Sender;
|
||||
use err::thiserror;
|
||||
use err::ThisError;
|
||||
use futures_util::Future;
|
||||
use items_0::Events;
|
||||
use netpod::log::*;
|
||||
use netpod::range::evrange::NanoRange;
|
||||
use netpod::ScyllaConfig;
|
||||
use netpod::TsMs;
|
||||
use scylla::Session;
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum Error {
|
||||
@@ -24,7 +32,31 @@ impl err::ToErr for Error {
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Job {
|
||||
JobA(String, Sender<Result<String, Error>>),
|
||||
FindTsMsp(
|
||||
// series-id
|
||||
u64,
|
||||
ScyllaSeriesRange,
|
||||
Sender<Result<(VecDeque<TsMs>, VecDeque<TsMs>), Error>>,
|
||||
),
|
||||
ReadNextValues(ReadNextValues),
|
||||
}
|
||||
|
||||
struct ReadNextValues {
|
||||
futgen: Box<
|
||||
dyn FnOnce(
|
||||
Arc<Session>,
|
||||
Arc<StmtsEventsRt>,
|
||||
) -> Pin<Box<dyn Future<Output = Result<Box<dyn Events>, err::Error>> + Send>>
|
||||
+ Send,
|
||||
>,
|
||||
// fut: Pin<Box<dyn Future<Output = Result<Box<dyn Events>, Error>> + Send>>,
|
||||
tx: Sender<Result<Box<dyn Events>, Error>>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for ReadNextValues {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "ReadNextValues {{ .. }}")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -33,31 +65,59 @@ pub struct ScyllaQueue {
|
||||
}
|
||||
|
||||
impl ScyllaQueue {
|
||||
pub async fn job_a(&self, backend: &str) -> Result<Receiver<Result<String, Error>>, Error> {
|
||||
pub async fn find_ts_msp(
|
||||
&self,
|
||||
series: u64,
|
||||
range: ScyllaSeriesRange,
|
||||
) -> Result<(VecDeque<TsMs>, VecDeque<TsMs>), Error> {
|
||||
let (tx, rx) = async_channel::bounded(1);
|
||||
let job = Job::JobA(backend.into(), tx);
|
||||
let job = Job::FindTsMsp(series, range, tx);
|
||||
self.tx.send(job).await.map_err(|_| Error::ChannelSend)?;
|
||||
Ok(rx)
|
||||
let res = rx.recv().await.map_err(|_| Error::ChannelRecv)??;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub async fn read_next_values<F>(&self, futgen: F) -> Result<Box<dyn Events>, Error>
|
||||
where
|
||||
F: FnOnce(
|
||||
Arc<Session>,
|
||||
Arc<StmtsEventsRt>,
|
||||
) -> Pin<Box<dyn Future<Output = Result<Box<dyn Events>, err::Error>> + Send>>
|
||||
+ Send
|
||||
+ 'static,
|
||||
{
|
||||
let (tx, rx) = async_channel::bounded(1);
|
||||
let job = Job::ReadNextValues(ReadNextValues {
|
||||
futgen: Box::new(futgen),
|
||||
tx,
|
||||
});
|
||||
self.tx.send(job).await.map_err(|_| Error::ChannelSend)?;
|
||||
let res = rx.recv().await.map_err(|_| Error::ChannelRecv)??;
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ScyllaWorker {
|
||||
rx: Receiver<Job>,
|
||||
scy: Session,
|
||||
// pgjh: Option<JoinHandle<Result<(), err::Error>>>,
|
||||
scy: Arc<Session>,
|
||||
stmts_st: Arc<StmtsEventsRt>,
|
||||
}
|
||||
|
||||
impl ScyllaWorker {
|
||||
pub async fn new(scyconf: &ScyllaConfig) -> Result<(ScyllaQueue, Self), Error> {
|
||||
pub async fn new(
|
||||
scyconf_st: &ScyllaConfig,
|
||||
scyconf_mt: &ScyllaConfig,
|
||||
scyconf_lt: &ScyllaConfig,
|
||||
) -> Result<(ScyllaQueue, Self), Error> {
|
||||
let (tx, rx) = async_channel::bounded(64);
|
||||
let scy = create_scy_session_no_ks(scyconf).await?;
|
||||
let scy = create_scy_session_no_ks(scyconf_st).await?;
|
||||
let scy = Arc::new(scy);
|
||||
let rtpre = format!("{}.st_", scyconf_st.keyspace);
|
||||
let stmts_st = StmtsEventsRt::new(&rtpre, &scy).await?;
|
||||
let stmts_st = Arc::new(stmts_st);
|
||||
let queue = ScyllaQueue { tx };
|
||||
let worker = Self {
|
||||
rx,
|
||||
scy,
|
||||
// pgjh: Some(pgjh),
|
||||
};
|
||||
let worker = Self { rx, scy, stmts_st };
|
||||
Ok((queue, worker))
|
||||
}
|
||||
|
||||
@@ -72,12 +132,19 @@ impl ScyllaWorker {
|
||||
}
|
||||
};
|
||||
match job {
|
||||
Job::JobA(backend, tx) => {
|
||||
let res = Ok::<_, Error>(backend);
|
||||
Job::FindTsMsp(series, range, tx) => {
|
||||
let res = crate::events::find_ts_msp_worker(series, range, &self.stmts_st, &self.scy).await;
|
||||
if tx.send(res.map_err(Into::into)).await.is_err() {
|
||||
// TODO count for stats
|
||||
}
|
||||
}
|
||||
Job::ReadNextValues(job) => {
|
||||
let fut = (job.futgen)(self.scy.clone(), self.stmts_st.clone());
|
||||
let res = fut.await;
|
||||
if job.tx.send(res.map_err(Into::into)).await.is_err() {
|
||||
// TODO count for stats
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user