Move code
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
use crate::events2::prepare::StmtsEvents;
|
||||
use crate::range::ScyllaSeriesRange;
|
||||
use crate::worker::ScyllaQueue;
|
||||
use err::thiserror;
|
||||
@@ -22,7 +23,6 @@ use netpod::Shape;
|
||||
use netpod::TsMs;
|
||||
use netpod::TsNano;
|
||||
use scylla::frame::response::result::Row;
|
||||
use scylla::prepared_statement::PreparedStatement;
|
||||
use scylla::Session;
|
||||
use series::SeriesId;
|
||||
use std::collections::VecDeque;
|
||||
@@ -34,6 +34,7 @@ use std::task::Poll;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum Error {
|
||||
Prepare(#[from] crate::events2::prepare::Error),
|
||||
ScyllaQuery(#[from] scylla::transport::errors::QueryError),
|
||||
ScyllaNextRow(#[from] scylla::transport::iterator::NextRowError),
|
||||
ScyllaTypeConv(#[from] scylla::cql_to_rust::FromRowError),
|
||||
@@ -50,278 +51,6 @@ impl From<crate::worker::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StmtsLspShape {
|
||||
u8: PreparedStatement,
|
||||
u16: PreparedStatement,
|
||||
u32: PreparedStatement,
|
||||
u64: PreparedStatement,
|
||||
i8: PreparedStatement,
|
||||
i16: PreparedStatement,
|
||||
i32: PreparedStatement,
|
||||
i64: PreparedStatement,
|
||||
f32: PreparedStatement,
|
||||
f64: PreparedStatement,
|
||||
bool: PreparedStatement,
|
||||
string: PreparedStatement,
|
||||
}
|
||||
|
||||
impl StmtsLspShape {
|
||||
fn st(&self, stname: &str) -> Result<&PreparedStatement, Error> {
|
||||
let ret = match stname {
|
||||
"u8" => &self.u8,
|
||||
"u16" => &self.u16,
|
||||
"u32" => &self.u32,
|
||||
"u64" => &self.u64,
|
||||
"i8" => &self.i8,
|
||||
"i16" => &self.i16,
|
||||
"i32" => &self.i32,
|
||||
"i64" => &self.i64,
|
||||
"f32" => &self.f32,
|
||||
"f64" => &self.f64,
|
||||
"bool" => &self.bool,
|
||||
"string" => &self.string,
|
||||
_ => return Err(Error::MissingQuery(format!("no query for stname {stname}"))),
|
||||
};
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StmtsLspDir {
|
||||
scalar: StmtsLspShape,
|
||||
array: StmtsLspShape,
|
||||
}
|
||||
|
||||
impl StmtsLspDir {
|
||||
fn shape(&self, array: bool) -> &StmtsLspShape {
|
||||
if array {
|
||||
&self.array
|
||||
} else {
|
||||
&self.scalar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StmtsEventsRt {
|
||||
ts_msp_fwd: PreparedStatement,
|
||||
ts_msp_bck: PreparedStatement,
|
||||
lsp_fwd_val: StmtsLspDir,
|
||||
lsp_bck_val: StmtsLspDir,
|
||||
lsp_fwd_ts: StmtsLspDir,
|
||||
lsp_bck_ts: StmtsLspDir,
|
||||
}
|
||||
|
||||
impl StmtsEventsRt {
|
||||
fn lsp(&self, bck: bool, val: bool) -> &StmtsLspDir {
|
||||
if bck {
|
||||
if val {
|
||||
&self.lsp_bck_val
|
||||
} else {
|
||||
&self.lsp_bck_ts
|
||||
}
|
||||
} else {
|
||||
if val {
|
||||
&self.lsp_fwd_val
|
||||
} else {
|
||||
&self.lsp_fwd_ts
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StmtsEvents {
|
||||
st: StmtsEventsRt,
|
||||
mt: StmtsEventsRt,
|
||||
lt: StmtsEventsRt,
|
||||
}
|
||||
|
||||
async fn make_msp_dir(ks: &str, rt: &RetentionTime, bck: bool, scy: &Session) -> Result<PreparedStatement, Error> {
|
||||
let table_name = "ts_msp";
|
||||
let select_cond = if bck {
|
||||
"ts_msp < ? order by ts_msp desc limit 2"
|
||||
} else {
|
||||
"ts_msp >= ? and ts_msp < ?"
|
||||
};
|
||||
let cql = format!(
|
||||
"select ts_msp from {}.{}{} where series = ? and {}",
|
||||
ks,
|
||||
rt.table_prefix(),
|
||||
table_name,
|
||||
select_cond
|
||||
);
|
||||
let qu = scy.prepare(cql).await?;
|
||||
Ok(qu)
|
||||
}
|
||||
|
||||
async fn make_lsp(
|
||||
ks: &str,
|
||||
rt: &RetentionTime,
|
||||
shapepre: &str,
|
||||
stname: &str,
|
||||
values: &str,
|
||||
bck: bool,
|
||||
scy: &Session,
|
||||
) -> Result<PreparedStatement, Error> {
|
||||
let select_cond = if bck {
|
||||
"ts_lsp < ? order by ts_lsp desc limit 1"
|
||||
} else {
|
||||
"ts_lsp >= ? and ts_lsp < ?"
|
||||
};
|
||||
let cql = format!(
|
||||
concat!(
|
||||
"select {} from {}.{}events_{}_{}",
|
||||
" where series = ? and ts_msp = ? and {}"
|
||||
),
|
||||
values,
|
||||
ks,
|
||||
rt.table_prefix(),
|
||||
shapepre,
|
||||
stname,
|
||||
select_cond
|
||||
);
|
||||
let qu = scy.prepare(cql).await?;
|
||||
Ok(qu)
|
||||
}
|
||||
|
||||
async fn make_lsp_shape(
|
||||
ks: &str,
|
||||
rt: &RetentionTime,
|
||||
shapepre: &str,
|
||||
values: &str,
|
||||
bck: bool,
|
||||
scy: &Session,
|
||||
) -> Result<StmtsLspShape, Error> {
|
||||
let values = if shapepre.contains("array") {
|
||||
values.replace("value", "valueblob")
|
||||
} else {
|
||||
values.into()
|
||||
};
|
||||
let values = &values;
|
||||
let maker = |stname| make_lsp(ks, rt, shapepre, stname, values, bck, scy);
|
||||
let ret = StmtsLspShape {
|
||||
u8: maker("u8").await?,
|
||||
u16: maker("u16").await?,
|
||||
u32: maker("u32").await?,
|
||||
u64: maker("u64").await?,
|
||||
i8: maker("i8").await?,
|
||||
i16: maker("i16").await?,
|
||||
i32: maker("i32").await?,
|
||||
i64: maker("i64").await?,
|
||||
f32: maker("f32").await?,
|
||||
f64: maker("f64").await?,
|
||||
bool: maker("bool").await?,
|
||||
string: maker("string").await?,
|
||||
};
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
async fn make_lsp_dir(
|
||||
ks: &str,
|
||||
rt: &RetentionTime,
|
||||
values: &str,
|
||||
bck: bool,
|
||||
scy: &Session,
|
||||
) -> Result<StmtsLspDir, Error> {
|
||||
let ret = StmtsLspDir {
|
||||
scalar: make_lsp_shape(ks, rt, "scalar", values, bck, scy).await?,
|
||||
array: make_lsp_shape(ks, rt, "array", values, bck, scy).await?,
|
||||
};
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
async fn make_rt(ks: &str, rt: &RetentionTime, scy: &Session) -> Result<StmtsEventsRt, Error> {
|
||||
let ret = StmtsEventsRt {
|
||||
ts_msp_fwd: make_msp_dir(ks, rt, false, scy).await?,
|
||||
ts_msp_bck: make_msp_dir(ks, rt, true, scy).await?,
|
||||
lsp_fwd_val: make_lsp_dir(ks, rt, "ts_lsp, pulse, value", false, scy).await?,
|
||||
lsp_bck_val: make_lsp_dir(ks, rt, "ts_lsp, pulse, value", true, scy).await?,
|
||||
lsp_fwd_ts: make_lsp_dir(ks, rt, "ts_lsp, pulse", false, scy).await?,
|
||||
lsp_bck_ts: make_lsp_dir(ks, rt, "ts_lsp, pulse", true, scy).await?,
|
||||
};
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
impl StmtsEvents {
|
||||
pub(super) async fn new(ks: [&str; 3], scy: &Session) -> Result<Self, Error> {
|
||||
let ret = StmtsEvents {
|
||||
st: make_rt(ks[0], &RetentionTime::Short, scy).await?,
|
||||
mt: make_rt(ks[1], &RetentionTime::Medium, scy).await?,
|
||||
lt: make_rt(ks[2], &RetentionTime::Long, scy).await?,
|
||||
};
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
fn rt(&self, rt: &RetentionTime) -> &StmtsEventsRt {
|
||||
match rt {
|
||||
RetentionTime::Short => &self.st,
|
||||
RetentionTime::Medium => &self.mt,
|
||||
RetentionTime::Long => &&self.lt,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) async fn find_ts_msp(
|
||||
rt: &RetentionTime,
|
||||
series: u64,
|
||||
range: ScyllaSeriesRange,
|
||||
bck: bool,
|
||||
stmts: &StmtsEvents,
|
||||
scy: &Session,
|
||||
) -> Result<VecDeque<TsMs>, Error> {
|
||||
trace!("find_ts_msp series {:?} {:?} {:?} bck {}", rt, series, range, bck);
|
||||
if bck {
|
||||
find_ts_msp_bck(rt, series, range, stmts, scy).await
|
||||
} else {
|
||||
find_ts_msp_fwd(rt, series, range, stmts, scy).await
|
||||
}
|
||||
}
|
||||
|
||||
async fn find_ts_msp_fwd(
|
||||
rt: &RetentionTime,
|
||||
series: u64,
|
||||
range: ScyllaSeriesRange,
|
||||
stmts: &StmtsEvents,
|
||||
scy: &Session,
|
||||
) -> Result<VecDeque<TsMs>, Error> {
|
||||
let mut ret = VecDeque::new();
|
||||
// TODO time range truncation can be handled better
|
||||
let params = (series as i64, range.beg().ms() as i64, 1 + range.end().ms() as i64);
|
||||
let mut res = scy
|
||||
.execute_iter(stmts.rt(rt).ts_msp_fwd.clone(), params)
|
||||
.await?
|
||||
.into_typed::<(i64,)>();
|
||||
while let Some(x) = res.next().await {
|
||||
let row = x?;
|
||||
let ts = TsMs::from_ms_u64(row.0 as u64);
|
||||
ret.push_back(ts);
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
async fn find_ts_msp_bck(
|
||||
rt: &RetentionTime,
|
||||
series: u64,
|
||||
range: ScyllaSeriesRange,
|
||||
stmts: &StmtsEvents,
|
||||
scy: &Session,
|
||||
) -> Result<VecDeque<TsMs>, Error> {
|
||||
let mut ret = VecDeque::new();
|
||||
let params = (series as i64, range.beg().ms() as i64);
|
||||
let mut res = scy
|
||||
.execute_iter(stmts.rt(rt).ts_msp_bck.clone(), params)
|
||||
.await?
|
||||
.into_typed::<(i64,)>();
|
||||
while let Some(x) = res.next().await {
|
||||
let row = x?;
|
||||
let ts = TsMs::from_ms_u64(row.0 as u64);
|
||||
ret.push_front(ts);
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
pub(super) trait ValTy: Sized + 'static {
|
||||
type ScaTy: ScalarOps + std::default::Default;
|
||||
type ScyTy: scylla::cql_to_rust::FromCqlVal<scylla::frame::response::result::CqlValue>;
|
||||
|
||||
@@ -3,3 +3,4 @@ pub mod firstbefore;
|
||||
pub mod mergert;
|
||||
pub mod msp;
|
||||
pub mod nonempty;
|
||||
pub mod prepare;
|
||||
|
||||
@@ -22,12 +22,35 @@ use std::pin::Pin;
|
||||
use std::task::Context;
|
||||
use std::task::Poll;
|
||||
|
||||
#[allow(unused)]
|
||||
macro_rules! trace_emit {
|
||||
($($arg:tt)*) => {
|
||||
if true {
|
||||
trace!($($arg)*);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
macro_rules! warn_item {
|
||||
($($arg:tt)*) => {
|
||||
if true {
|
||||
debug!($($arg)*);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum Error {
|
||||
Worker(#[from] crate::worker::Error),
|
||||
Events(#[from] crate::events::Error),
|
||||
Msp(#[from] crate::events2::msp::Error),
|
||||
Unordered,
|
||||
OutOfRange,
|
||||
BadBatch,
|
||||
Logic,
|
||||
Merge(#[from] items_0::MergeError),
|
||||
TruncateLogic,
|
||||
}
|
||||
|
||||
struct FetchMsp {
|
||||
@@ -180,51 +203,75 @@ impl Stream for EventsStreamRt {
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
use Poll::*;
|
||||
loop {
|
||||
if let Some(item) = self.out.pop_front() {
|
||||
if let Some(mut item) = self.out.pop_front() {
|
||||
if !item.verify() {
|
||||
debug!("{}bad item {:?}", "\n\n--------------------------\n", item);
|
||||
warn_item!("{}bad item {:?}", "\n\n--------------------------\n", item);
|
||||
self.state = State::Done;
|
||||
break Ready(Some(Err(Error::Logic)));
|
||||
break Ready(Some(Err(Error::BadBatch)));
|
||||
}
|
||||
if let Some(item_min) = item.ts_min() {
|
||||
if item_min < self.range.beg().ns() {
|
||||
debug!(
|
||||
warn_item!(
|
||||
"{}out of range error A {} {:?}",
|
||||
"\n\n--------------------------\n", item_min, self.range
|
||||
"\n\n--------------------------\n",
|
||||
item_min,
|
||||
self.range
|
||||
);
|
||||
self.state = State::Done;
|
||||
break Ready(Some(Err(Error::Logic)));
|
||||
break Ready(Some(Err(Error::OutOfRange)));
|
||||
}
|
||||
if item_min < self.ts_seen_max {
|
||||
debug!(
|
||||
warn_item!(
|
||||
"{}ordering error A {} {}",
|
||||
"\n\n--------------------------\n", item_min, self.ts_seen_max
|
||||
"\n\n--------------------------\n",
|
||||
item_min,
|
||||
self.ts_seen_max
|
||||
);
|
||||
self.state = State::Done;
|
||||
break Ready(Some(Err(Error::Logic)));
|
||||
let mut r = items_2::merger::Mergeable::new_empty(&item);
|
||||
match items_2::merger::Mergeable::find_highest_index_lt(&item, self.ts_seen_max) {
|
||||
Some(ix) => {
|
||||
match items_2::merger::Mergeable::drain_into(&mut item, &mut r, (0, ix)) {
|
||||
Ok(()) => {}
|
||||
Err(e) => {
|
||||
self.state = State::Done;
|
||||
break Ready(Some(Err(e.into())));
|
||||
}
|
||||
}
|
||||
// self.state = State::Done;
|
||||
// break Ready(Some(Err(Error::Unordered)));
|
||||
}
|
||||
None => {
|
||||
self.state = State::Done;
|
||||
break Ready(Some(Err(Error::TruncateLogic)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(item_max) = item.ts_max() {
|
||||
if item_max >= self.range.end().ns() {
|
||||
debug!(
|
||||
warn_item!(
|
||||
"{}out of range error B {} {:?}",
|
||||
"\n\n--------------------------\n", item_max, self.range
|
||||
"\n\n--------------------------\n",
|
||||
item_max,
|
||||
self.range
|
||||
);
|
||||
self.state = State::Done;
|
||||
break Ready(Some(Err(Error::Logic)));
|
||||
break Ready(Some(Err(Error::OutOfRange)));
|
||||
}
|
||||
if item_max < self.ts_seen_max {
|
||||
debug!(
|
||||
warn_item!(
|
||||
"{}ordering error B {} {}",
|
||||
"\n\n--------------------------\n", item_max, self.ts_seen_max
|
||||
"\n\n--------------------------\n",
|
||||
item_max,
|
||||
self.ts_seen_max
|
||||
);
|
||||
self.state = State::Done;
|
||||
break Ready(Some(Err(Error::Logic)));
|
||||
break Ready(Some(Err(Error::Unordered)));
|
||||
} else {
|
||||
self.ts_seen_max = item_max;
|
||||
}
|
||||
}
|
||||
debug!("deliver item {}", item.output_info());
|
||||
trace_emit!("deliver item {}", item.output_info());
|
||||
break Ready(Some(Ok(ChannelEvents::Events(item))));
|
||||
}
|
||||
break match &mut self.state {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use super::prepare::StmtsEvents;
|
||||
use crate::range::ScyllaSeriesRange;
|
||||
use crate::worker::ScyllaQueue;
|
||||
use err::thiserror;
|
||||
@@ -5,8 +6,11 @@ use err::ThisError;
|
||||
use futures_util::Future;
|
||||
use futures_util::FutureExt;
|
||||
use futures_util::Stream;
|
||||
use futures_util::StreamExt;
|
||||
use netpod::log::*;
|
||||
use netpod::ttl::RetentionTime;
|
||||
use netpod::TsMs;
|
||||
use scylla::Session;
|
||||
use series::SeriesId;
|
||||
use std::collections::VecDeque;
|
||||
use std::pin::Pin;
|
||||
@@ -15,8 +19,17 @@ use std::task::Poll;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum Error {
|
||||
Worker(#[from] crate::worker::Error),
|
||||
Logic,
|
||||
#[error("Worker({0})")]
|
||||
Worker(Box<crate::worker::Error>),
|
||||
ScyllaQuery(#[from] scylla::transport::errors::QueryError),
|
||||
ScyllaRow(#[from] scylla::transport::iterator::NextRowError),
|
||||
}
|
||||
|
||||
impl From<crate::worker::Error> for Error {
|
||||
fn from(value: crate::worker::Error) -> Self {
|
||||
Self::Worker(Box::new(value))
|
||||
}
|
||||
}
|
||||
|
||||
enum Resolvable<F>
|
||||
@@ -180,3 +193,62 @@ fn trait_assert_try() {
|
||||
fn phantomval<T>() -> T {
|
||||
panic!()
|
||||
}
|
||||
|
||||
pub async fn find_ts_msp(
|
||||
rt: &RetentionTime,
|
||||
series: u64,
|
||||
range: ScyllaSeriesRange,
|
||||
bck: bool,
|
||||
stmts: &StmtsEvents,
|
||||
scy: &Session,
|
||||
) -> Result<VecDeque<TsMs>, Error> {
|
||||
trace!("find_ts_msp series {:?} {:?} {:?} bck {}", rt, series, range, bck);
|
||||
if bck {
|
||||
find_ts_msp_bck(rt, series, range, stmts, scy).await
|
||||
} else {
|
||||
find_ts_msp_fwd(rt, series, range, stmts, scy).await
|
||||
}
|
||||
}
|
||||
|
||||
async fn find_ts_msp_fwd(
|
||||
rt: &RetentionTime,
|
||||
series: u64,
|
||||
range: ScyllaSeriesRange,
|
||||
stmts: &StmtsEvents,
|
||||
scy: &Session,
|
||||
) -> Result<VecDeque<TsMs>, Error> {
|
||||
let mut ret = VecDeque::new();
|
||||
// TODO time range truncation can be handled better
|
||||
let params = (series as i64, range.beg().ms() as i64, 1 + range.end().ms() as i64);
|
||||
let mut res = scy
|
||||
.execute_iter(stmts.rt(rt).ts_msp_fwd().clone(), params)
|
||||
.await?
|
||||
.into_typed::<(i64,)>();
|
||||
while let Some(x) = res.next().await {
|
||||
let row = x?;
|
||||
let ts = TsMs::from_ms_u64(row.0 as u64);
|
||||
ret.push_back(ts);
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
async fn find_ts_msp_bck(
|
||||
rt: &RetentionTime,
|
||||
series: u64,
|
||||
range: ScyllaSeriesRange,
|
||||
stmts: &StmtsEvents,
|
||||
scy: &Session,
|
||||
) -> Result<VecDeque<TsMs>, Error> {
|
||||
let mut ret = VecDeque::new();
|
||||
let params = (series as i64, range.beg().ms() as i64);
|
||||
let mut res = scy
|
||||
.execute_iter(stmts.rt(rt).ts_msp_bck().clone(), params)
|
||||
.await?
|
||||
.into_typed::<(i64,)>();
|
||||
while let Some(x) = res.next().await {
|
||||
let row = x?;
|
||||
let ts = TsMs::from_ms_u64(row.0 as u64);
|
||||
ret.push_front(ts);
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
238
crates/scyllaconn/src/events2/prepare.rs
Normal file
238
crates/scyllaconn/src/events2/prepare.rs
Normal file
@@ -0,0 +1,238 @@
|
||||
use err::thiserror;
|
||||
use err::ThisError;
|
||||
use netpod::ttl::RetentionTime;
|
||||
use scylla::prepared_statement::PreparedStatement;
|
||||
use scylla::Session;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum Error {
|
||||
ScyllaQuery(#[from] scylla::transport::errors::QueryError),
|
||||
ScyllaNextRow(#[from] scylla::transport::iterator::NextRowError),
|
||||
ScyllaTypeConv(#[from] scylla::cql_to_rust::FromRowError),
|
||||
ScyllaWorker(Box<crate::worker::Error>),
|
||||
MissingQuery(String),
|
||||
RangeEndOverflow,
|
||||
InvalidFuture,
|
||||
TestError(String),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StmtsLspShape {
|
||||
u8: PreparedStatement,
|
||||
u16: PreparedStatement,
|
||||
u32: PreparedStatement,
|
||||
u64: PreparedStatement,
|
||||
i8: PreparedStatement,
|
||||
i16: PreparedStatement,
|
||||
i32: PreparedStatement,
|
||||
i64: PreparedStatement,
|
||||
f32: PreparedStatement,
|
||||
f64: PreparedStatement,
|
||||
bool: PreparedStatement,
|
||||
string: PreparedStatement,
|
||||
}
|
||||
|
||||
impl StmtsLspShape {
|
||||
pub fn st(&self, stname: &str) -> Result<&PreparedStatement, Error> {
|
||||
let ret = match stname {
|
||||
"u8" => &self.u8,
|
||||
"u16" => &self.u16,
|
||||
"u32" => &self.u32,
|
||||
"u64" => &self.u64,
|
||||
"i8" => &self.i8,
|
||||
"i16" => &self.i16,
|
||||
"i32" => &self.i32,
|
||||
"i64" => &self.i64,
|
||||
"f32" => &self.f32,
|
||||
"f64" => &self.f64,
|
||||
"bool" => &self.bool,
|
||||
"string" => &self.string,
|
||||
_ => return Err(Error::MissingQuery(format!("no query for stname {stname}"))),
|
||||
};
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StmtsLspDir {
|
||||
scalar: StmtsLspShape,
|
||||
array: StmtsLspShape,
|
||||
}
|
||||
|
||||
impl StmtsLspDir {
|
||||
pub fn shape(&self, array: bool) -> &StmtsLspShape {
|
||||
if array {
|
||||
&self.array
|
||||
} else {
|
||||
&self.scalar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StmtsEventsRt {
|
||||
ts_msp_fwd: PreparedStatement,
|
||||
ts_msp_bck: PreparedStatement,
|
||||
lsp_fwd_val: StmtsLspDir,
|
||||
lsp_bck_val: StmtsLspDir,
|
||||
lsp_fwd_ts: StmtsLspDir,
|
||||
lsp_bck_ts: StmtsLspDir,
|
||||
}
|
||||
|
||||
impl StmtsEventsRt {
|
||||
pub fn ts_msp_fwd(&self) -> &PreparedStatement {
|
||||
&self.ts_msp_fwd
|
||||
}
|
||||
|
||||
pub fn ts_msp_bck(&self) -> &PreparedStatement {
|
||||
&self.ts_msp_bck
|
||||
}
|
||||
|
||||
pub fn lsp(&self, bck: bool, val: bool) -> &StmtsLspDir {
|
||||
if bck {
|
||||
if val {
|
||||
&self.lsp_bck_val
|
||||
} else {
|
||||
&self.lsp_bck_ts
|
||||
}
|
||||
} else {
|
||||
if val {
|
||||
&self.lsp_fwd_val
|
||||
} else {
|
||||
&self.lsp_fwd_ts
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn make_msp_dir(ks: &str, rt: &RetentionTime, bck: bool, scy: &Session) -> Result<PreparedStatement, Error> {
|
||||
let table_name = "ts_msp";
|
||||
let select_cond = if bck {
|
||||
"ts_msp < ? order by ts_msp desc limit 2"
|
||||
} else {
|
||||
"ts_msp >= ? and ts_msp < ?"
|
||||
};
|
||||
let cql = format!(
|
||||
"select ts_msp from {}.{}{} where series = ? and {}",
|
||||
ks,
|
||||
rt.table_prefix(),
|
||||
table_name,
|
||||
select_cond
|
||||
);
|
||||
let qu = scy.prepare(cql).await?;
|
||||
Ok(qu)
|
||||
}
|
||||
|
||||
async fn make_lsp(
|
||||
ks: &str,
|
||||
rt: &RetentionTime,
|
||||
shapepre: &str,
|
||||
stname: &str,
|
||||
values: &str,
|
||||
bck: bool,
|
||||
scy: &Session,
|
||||
) -> Result<PreparedStatement, Error> {
|
||||
let select_cond = if bck {
|
||||
"ts_lsp < ? order by ts_lsp desc limit 1"
|
||||
} else {
|
||||
"ts_lsp >= ? and ts_lsp < ?"
|
||||
};
|
||||
let cql = format!(
|
||||
concat!(
|
||||
"select {} from {}.{}events_{}_{}",
|
||||
" where series = ? and ts_msp = ? and {}"
|
||||
),
|
||||
values,
|
||||
ks,
|
||||
rt.table_prefix(),
|
||||
shapepre,
|
||||
stname,
|
||||
select_cond
|
||||
);
|
||||
let qu = scy.prepare(cql).await?;
|
||||
Ok(qu)
|
||||
}
|
||||
|
||||
async fn make_lsp_shape(
|
||||
ks: &str,
|
||||
rt: &RetentionTime,
|
||||
shapepre: &str,
|
||||
values: &str,
|
||||
bck: bool,
|
||||
scy: &Session,
|
||||
) -> Result<StmtsLspShape, Error> {
|
||||
let values = if shapepre.contains("array") {
|
||||
values.replace("value", "valueblob")
|
||||
} else {
|
||||
values.into()
|
||||
};
|
||||
let values = &values;
|
||||
let maker = |stname| make_lsp(ks, rt, shapepre, stname, values, bck, scy);
|
||||
let ret = StmtsLspShape {
|
||||
u8: maker("u8").await?,
|
||||
u16: maker("u16").await?,
|
||||
u32: maker("u32").await?,
|
||||
u64: maker("u64").await?,
|
||||
i8: maker("i8").await?,
|
||||
i16: maker("i16").await?,
|
||||
i32: maker("i32").await?,
|
||||
i64: maker("i64").await?,
|
||||
f32: maker("f32").await?,
|
||||
f64: maker("f64").await?,
|
||||
bool: maker("bool").await?,
|
||||
string: maker("string").await?,
|
||||
};
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
async fn make_lsp_dir(
|
||||
ks: &str,
|
||||
rt: &RetentionTime,
|
||||
values: &str,
|
||||
bck: bool,
|
||||
scy: &Session,
|
||||
) -> Result<StmtsLspDir, Error> {
|
||||
let ret = StmtsLspDir {
|
||||
scalar: make_lsp_shape(ks, rt, "scalar", values, bck, scy).await?,
|
||||
array: make_lsp_shape(ks, rt, "array", values, bck, scy).await?,
|
||||
};
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
async fn make_rt(ks: &str, rt: &RetentionTime, scy: &Session) -> Result<StmtsEventsRt, Error> {
|
||||
let ret = StmtsEventsRt {
|
||||
ts_msp_fwd: make_msp_dir(ks, rt, false, scy).await?,
|
||||
ts_msp_bck: make_msp_dir(ks, rt, true, scy).await?,
|
||||
lsp_fwd_val: make_lsp_dir(ks, rt, "ts_lsp, pulse, value", false, scy).await?,
|
||||
lsp_bck_val: make_lsp_dir(ks, rt, "ts_lsp, pulse, value", true, scy).await?,
|
||||
lsp_fwd_ts: make_lsp_dir(ks, rt, "ts_lsp, pulse", false, scy).await?,
|
||||
lsp_bck_ts: make_lsp_dir(ks, rt, "ts_lsp, pulse", true, scy).await?,
|
||||
};
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StmtsEvents {
|
||||
st: StmtsEventsRt,
|
||||
mt: StmtsEventsRt,
|
||||
lt: StmtsEventsRt,
|
||||
}
|
||||
|
||||
impl StmtsEvents {
|
||||
pub async fn new(ks: [&str; 3], scy: &Session) -> Result<Self, Error> {
|
||||
let ret = StmtsEvents {
|
||||
st: make_rt(ks[0], &RetentionTime::Short, scy).await?,
|
||||
mt: make_rt(ks[1], &RetentionTime::Medium, scy).await?,
|
||||
lt: make_rt(ks[2], &RetentionTime::Long, scy).await?,
|
||||
};
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
pub fn rt(&self, rt: &RetentionTime) -> &StmtsEventsRt {
|
||||
match rt {
|
||||
RetentionTime::Short => &self.st,
|
||||
RetentionTime::Medium => &self.mt,
|
||||
RetentionTime::Long => &&self.lt,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::conn::create_scy_session_no_ks;
|
||||
use crate::events::StmtsEvents;
|
||||
use crate::events2::prepare::StmtsEvents;
|
||||
use crate::range::ScyllaSeriesRange;
|
||||
use async_channel::Receiver;
|
||||
use async_channel::Sender;
|
||||
@@ -19,8 +19,11 @@ use std::sync::Arc;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum Error {
|
||||
#[error("ScyllaConnection({0})")]
|
||||
ScyllaConnection(err::Error),
|
||||
Prepare(#[from] crate::events2::prepare::Error),
|
||||
EventsQuery(#[from] crate::events::Error),
|
||||
Msp(#[from] crate::events2::msp::Error),
|
||||
ChannelSend,
|
||||
ChannelRecv,
|
||||
Join,
|
||||
@@ -145,7 +148,7 @@ impl ScyllaWorker {
|
||||
};
|
||||
match job {
|
||||
Job::FindTsMsp(rt, series, range, bck, tx) => {
|
||||
let res = crate::events::find_ts_msp(&rt, series, range, bck, &stmts, &scy).await;
|
||||
let res = crate::events2::msp::find_ts_msp(&rt, series, range, bck, &stmts, &scy).await;
|
||||
if tx.send(res.map_err(Into::into)).await.is_err() {
|
||||
// TODO count for stats
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user