Read back array data from value blob
This commit is contained in:
@@ -64,7 +64,7 @@ async fn go() -> Result<(), Error> {
|
|||||||
};
|
};
|
||||||
match opts.subcmd {
|
match opts.subcmd {
|
||||||
SubCmd::Retrieval(subcmd) => {
|
SubCmd::Retrieval(subcmd) => {
|
||||||
info!("daqbuffer version {} +0002", clap::crate_version!());
|
info!("daqbuffer version {} +0003", clap::crate_version!());
|
||||||
info!(" service_version {}", service_version);
|
info!(" service_version {}", service_version);
|
||||||
if false {
|
if false {
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ use httpclient::Requ;
|
|||||||
use httpclient::StreamResponse;
|
use httpclient::StreamResponse;
|
||||||
use netpod::log::*;
|
use netpod::log::*;
|
||||||
use netpod::NodeConfigCached;
|
use netpod::NodeConfigCached;
|
||||||
use netpod::ServiceVersion;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Debug, ThisError)]
|
#[derive(Debug, ThisError)]
|
||||||
@@ -85,7 +84,7 @@ impl EventDataHandler {
|
|||||||
.await
|
.await
|
||||||
.map_err(|_| EventDataError::InternalError)?;
|
.map_err(|_| EventDataError::InternalError)?;
|
||||||
let (evsubq,) = nodenet::conn::events_parse_input_query(frames).map_err(|_| EventDataError::QueryParse)?;
|
let (evsubq,) = nodenet::conn::events_parse_input_query(frames).map_err(|_| EventDataError::QueryParse)?;
|
||||||
let stream = nodenet::conn::create_response_bytes_stream(evsubq, ncc)
|
let stream = nodenet::conn::create_response_bytes_stream(evsubq, shared_res.scyqueue.as_ref(), ncc)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| EventDataError::Error(Box::new(e)))?;
|
.map_err(|e| EventDataError::Error(Box::new(e)))?;
|
||||||
let ret = response(StatusCode::OK)
|
let ret = response(StatusCode::OK)
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ use netpod::APP_JSON;
|
|||||||
use panic::AssertUnwindSafe;
|
use panic::AssertUnwindSafe;
|
||||||
use panic::UnwindSafe;
|
use panic::UnwindSafe;
|
||||||
use pin::Pin;
|
use pin::Pin;
|
||||||
|
use scyllaconn::worker::ScyllaQueue;
|
||||||
|
use scyllaconn::worker::ScyllaWorker;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::net;
|
use std::net;
|
||||||
@@ -102,11 +104,12 @@ impl ::err::ToErr for RetrievalError {
|
|||||||
|
|
||||||
pub struct ServiceSharedResources {
|
pub struct ServiceSharedResources {
|
||||||
pgqueue: PgQueue,
|
pgqueue: PgQueue,
|
||||||
|
scyqueue: Option<ScyllaQueue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServiceSharedResources {
|
impl ServiceSharedResources {
|
||||||
pub fn new(pgqueue: PgQueue) -> Self {
|
pub fn new(pgqueue: PgQueue, scyqueue: Option<ScyllaQueue>) -> Self {
|
||||||
Self { pgqueue }
|
Self { pgqueue, scyqueue }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +122,21 @@ pub async fn host(ncc: NodeConfigCached, service_version: ServiceVersion) -> Res
|
|||||||
// let rawjh = taskrun::spawn(nodenet::conn::events_service(node_config.clone()));
|
// let rawjh = taskrun::spawn(nodenet::conn::events_service(node_config.clone()));
|
||||||
let (pgqueue, pgworker) = PgWorker::new(&ncc.node_config.cluster.database).await?;
|
let (pgqueue, pgworker) = PgWorker::new(&ncc.node_config.cluster.database).await?;
|
||||||
let pgworker_jh = taskrun::spawn(pgworker.work());
|
let pgworker_jh = taskrun::spawn(pgworker.work());
|
||||||
let shared_res = ServiceSharedResources::new(pgqueue);
|
let scyqueue = if let (Some(st), Some(mt), Some(lt)) = (
|
||||||
|
ncc.node_config.cluster.scylla_st(),
|
||||||
|
ncc.node_config.cluster.scylla_mt(),
|
||||||
|
ncc.node_config.cluster.scylla_lt(),
|
||||||
|
) {
|
||||||
|
let (scyqueue, scylla_worker) = ScyllaWorker::new(st, mt, lt).await.map_err(|e| {
|
||||||
|
error!("{e}");
|
||||||
|
RetrievalError::TextError(e.to_string())
|
||||||
|
})?;
|
||||||
|
let scylla_worker_jh = taskrun::spawn(scylla_worker.work());
|
||||||
|
Some(scyqueue)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let shared_res = ServiceSharedResources::new(pgqueue, scyqueue);
|
||||||
let shared_res = Arc::new(shared_res);
|
let shared_res = Arc::new(shared_res);
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
let bind_addr = SocketAddr::from_str(&format!("{}:{}", ncc.node.listen(), ncc.node.port))?;
|
let bind_addr = SocketAddr::from_str(&format!("{}:{}", ncc.node.listen(), ncc.node.port))?;
|
||||||
@@ -136,7 +153,6 @@ pub async fn host(ncc: NodeConfigCached, service_version: ServiceVersion) -> Res
|
|||||||
let service_version = service_version.clone();
|
let service_version = service_version.clone();
|
||||||
let io = TokioIo::new(stream);
|
let io = TokioIo::new(stream);
|
||||||
let shared_res = shared_res.clone();
|
let shared_res = shared_res.clone();
|
||||||
// let shared_res = &shared_res;
|
|
||||||
tokio::task::spawn(async move {
|
tokio::task::spawn(async move {
|
||||||
let res = hyper::server::conn::http1::Builder::new()
|
let res = hyper::server::conn::http1::Builder::new()
|
||||||
.serve_connection(
|
.serve_connection(
|
||||||
|
|||||||
+28
-14
@@ -17,7 +17,6 @@ use items_2::empty::empty_events_dyn_ev;
|
|||||||
use items_2::framable::EventQueryJsonStringFrame;
|
use items_2::framable::EventQueryJsonStringFrame;
|
||||||
use items_2::framable::Framable;
|
use items_2::framable::Framable;
|
||||||
use items_2::frame::decode_frame;
|
use items_2::frame::decode_frame;
|
||||||
use items_2::frame::make_error_frame;
|
|
||||||
use items_2::frame::make_term_frame;
|
use items_2::frame::make_term_frame;
|
||||||
use items_2::inmem::InMemoryFrame;
|
use items_2::inmem::InMemoryFrame;
|
||||||
use netpod::histo::HistoLog2;
|
use netpod::histo::HistoLog2;
|
||||||
@@ -26,6 +25,7 @@ use netpod::NodeConfigCached;
|
|||||||
use netpod::ReqCtxArc;
|
use netpod::ReqCtxArc;
|
||||||
use query::api4::events::EventsSubQuery;
|
use query::api4::events::EventsSubQuery;
|
||||||
use query::api4::events::Frame1Parts;
|
use query::api4::events::Frame1Parts;
|
||||||
|
use scyllaconn::worker::ScyllaQueue;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use streams::frames::inmem::BoxedBytesStream;
|
use streams::frames::inmem::BoxedBytesStream;
|
||||||
@@ -45,13 +45,14 @@ mod test;
|
|||||||
#[derive(Debug, ThisError)]
|
#[derive(Debug, ThisError)]
|
||||||
pub enum NodeNetError {}
|
pub enum NodeNetError {}
|
||||||
|
|
||||||
pub async fn events_service(node_config: NodeConfigCached) -> Result<(), Error> {
|
pub async fn events_service(ncc: NodeConfigCached) -> Result<(), Error> {
|
||||||
let addr = format!("{}:{}", node_config.node.listen(), node_config.node.port_raw);
|
let scyqueue = err::todoval();
|
||||||
|
let addr = format!("{}:{}", ncc.node.listen(), ncc.node.port_raw);
|
||||||
let lis = tokio::net::TcpListener::bind(addr).await?;
|
let lis = tokio::net::TcpListener::bind(addr).await?;
|
||||||
loop {
|
loop {
|
||||||
match lis.accept().await {
|
match lis.accept().await {
|
||||||
Ok((stream, addr)) => {
|
Ok((stream, addr)) => {
|
||||||
taskrun::spawn(events_conn_handler(stream, addr, node_config.clone()));
|
taskrun::spawn(events_conn_handler(stream, addr, scyqueue, ncc.clone()));
|
||||||
}
|
}
|
||||||
Err(e) => Err(e)?,
|
Err(e) => Err(e)?,
|
||||||
}
|
}
|
||||||
@@ -76,15 +77,16 @@ impl<E: Into<Error>> From<(E, OwnedWriteHalf)> for ConnErr {
|
|||||||
async fn make_channel_events_stream_data(
|
async fn make_channel_events_stream_data(
|
||||||
subq: EventsSubQuery,
|
subq: EventsSubQuery,
|
||||||
reqctx: ReqCtxArc,
|
reqctx: ReqCtxArc,
|
||||||
|
scyqueue: Option<&ScyllaQueue>,
|
||||||
ncc: &NodeConfigCached,
|
ncc: &NodeConfigCached,
|
||||||
) -> Result<Pin<Box<dyn Stream<Item = Sitemty<ChannelEvents>> + Send>>, Error> {
|
) -> Result<Pin<Box<dyn Stream<Item = Sitemty<ChannelEvents>> + Send>>, Error> {
|
||||||
if subq.backend() == TEST_BACKEND {
|
if subq.backend() == TEST_BACKEND {
|
||||||
let node_count = ncc.node_config.cluster.nodes.len() as u64;
|
let node_count = ncc.node_config.cluster.nodes.len() as u64;
|
||||||
let node_ix = ncc.ix as u64;
|
let node_ix = ncc.ix as u64;
|
||||||
streams::generators::make_test_channel_events_stream_data(subq, node_count, node_ix)
|
streams::generators::make_test_channel_events_stream_data(subq, node_count, node_ix)
|
||||||
} else if let Some(scyconf) = &ncc.node_config.cluster.scylla_st() {
|
} else if let Some(scyqueue) = scyqueue {
|
||||||
let cfg = subq.ch_conf().to_scylla()?;
|
let cfg = subq.ch_conf().to_scylla()?;
|
||||||
scylla_channel_event_stream(subq, cfg, scyconf, ncc).await
|
scylla_channel_event_stream(subq, cfg, scyqueue).await
|
||||||
} else if let Some(_) = &ncc.node.channel_archiver {
|
} else if let Some(_) = &ncc.node.channel_archiver {
|
||||||
let e = Error::with_msg_no_trace("archapp not built");
|
let e = Error::with_msg_no_trace("archapp not built");
|
||||||
Err(e)
|
Err(e)
|
||||||
@@ -100,11 +102,12 @@ async fn make_channel_events_stream_data(
|
|||||||
async fn make_channel_events_stream(
|
async fn make_channel_events_stream(
|
||||||
subq: EventsSubQuery,
|
subq: EventsSubQuery,
|
||||||
reqctx: ReqCtxArc,
|
reqctx: ReqCtxArc,
|
||||||
|
scyqueue: Option<&ScyllaQueue>,
|
||||||
ncc: &NodeConfigCached,
|
ncc: &NodeConfigCached,
|
||||||
) -> Result<Pin<Box<dyn Stream<Item = Sitemty<ChannelEvents>> + Send>>, Error> {
|
) -> Result<Pin<Box<dyn Stream<Item = Sitemty<ChannelEvents>> + Send>>, Error> {
|
||||||
let empty = empty_events_dyn_ev(subq.ch_conf().scalar_type(), subq.ch_conf().shape())?;
|
let empty = empty_events_dyn_ev(subq.ch_conf().scalar_type(), subq.ch_conf().shape())?;
|
||||||
let empty = sitem_data(ChannelEvents::Events(empty));
|
let empty = sitem_data(ChannelEvents::Events(empty));
|
||||||
let stream = make_channel_events_stream_data(subq, reqctx, ncc).await?;
|
let stream = make_channel_events_stream_data(subq, reqctx, scyqueue, ncc).await?;
|
||||||
let ret = futures_util::stream::iter([empty]).chain(stream);
|
let ret = futures_util::stream::iter([empty]).chain(stream);
|
||||||
let ret = Box::pin(ret);
|
let ret = Box::pin(ret);
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
@@ -112,6 +115,7 @@ async fn make_channel_events_stream(
|
|||||||
|
|
||||||
pub async fn create_response_bytes_stream(
|
pub async fn create_response_bytes_stream(
|
||||||
evq: EventsSubQuery,
|
evq: EventsSubQuery,
|
||||||
|
scyqueue: Option<&ScyllaQueue>,
|
||||||
ncc: &NodeConfigCached,
|
ncc: &NodeConfigCached,
|
||||||
) -> Result<BoxedBytesStream, Error> {
|
) -> Result<BoxedBytesStream, Error> {
|
||||||
debug!(
|
debug!(
|
||||||
@@ -136,7 +140,7 @@ pub async fn create_response_bytes_stream(
|
|||||||
Ok(ret)
|
Ok(ret)
|
||||||
} else {
|
} else {
|
||||||
let mut tr = build_event_transform(evq.transform())?;
|
let mut tr = build_event_transform(evq.transform())?;
|
||||||
let stream = make_channel_events_stream(evq, reqctx, ncc).await?;
|
let stream = make_channel_events_stream(evq, reqctx, scyqueue, ncc).await?;
|
||||||
let stream = stream.map(move |x| {
|
let stream = stream.map(move |x| {
|
||||||
on_sitemty_data!(x, |x: ChannelEvents| {
|
on_sitemty_data!(x, |x: ChannelEvents| {
|
||||||
match x {
|
match x {
|
||||||
@@ -162,9 +166,10 @@ pub async fn create_response_bytes_stream(
|
|||||||
async fn events_conn_handler_with_reqid(
|
async fn events_conn_handler_with_reqid(
|
||||||
mut netout: OwnedWriteHalf,
|
mut netout: OwnedWriteHalf,
|
||||||
evq: EventsSubQuery,
|
evq: EventsSubQuery,
|
||||||
|
scyqueue: Option<&ScyllaQueue>,
|
||||||
ncc: &NodeConfigCached,
|
ncc: &NodeConfigCached,
|
||||||
) -> Result<(), ConnErr> {
|
) -> Result<(), ConnErr> {
|
||||||
let mut stream = match create_response_bytes_stream(evq, ncc).await {
|
let mut stream = match create_response_bytes_stream(evq, scyqueue, ncc).await {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(e) => return Err((e, netout))?,
|
Err(e) => return Err((e, netout))?,
|
||||||
};
|
};
|
||||||
@@ -283,6 +288,7 @@ async fn events_conn_handler_inner_try<INP>(
|
|||||||
netin: INP,
|
netin: INP,
|
||||||
netout: OwnedWriteHalf,
|
netout: OwnedWriteHalf,
|
||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
|
scyqueue: Option<&ScyllaQueue>,
|
||||||
ncc: &NodeConfigCached,
|
ncc: &NodeConfigCached,
|
||||||
) -> Result<(), ConnErr>
|
) -> Result<(), ConnErr>
|
||||||
where
|
where
|
||||||
@@ -300,19 +306,22 @@ where
|
|||||||
debug!("events_conn_handler sees: {evq:?}");
|
debug!("events_conn_handler sees: {evq:?}");
|
||||||
let reqid = evq.reqid();
|
let reqid = evq.reqid();
|
||||||
let span = tracing::info_span!("subreq", reqid = reqid);
|
let span = tracing::info_span!("subreq", reqid = reqid);
|
||||||
events_conn_handler_with_reqid(netout, evq, ncc).instrument(span).await
|
events_conn_handler_with_reqid(netout, evq, scyqueue, ncc)
|
||||||
|
.instrument(span)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn events_conn_handler_inner<INP>(
|
async fn events_conn_handler_inner<INP>(
|
||||||
netin: INP,
|
netin: INP,
|
||||||
netout: OwnedWriteHalf,
|
netout: OwnedWriteHalf,
|
||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
node_config: &NodeConfigCached,
|
scyqueue: Option<&ScyllaQueue>,
|
||||||
|
ncc: &NodeConfigCached,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
INP: Stream<Item = Result<Bytes, Error>> + Unpin,
|
INP: Stream<Item = Result<Bytes, Error>> + Unpin,
|
||||||
{
|
{
|
||||||
match events_conn_handler_inner_try(netin, netout, addr, node_config).await {
|
match events_conn_handler_inner_try(netin, netout, addr, scyqueue, ncc).await {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(ce) => {
|
Err(ce) => {
|
||||||
let mut out = ce.netout;
|
let mut out = ce.netout;
|
||||||
@@ -324,11 +333,16 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn events_conn_handler(stream: TcpStream, addr: SocketAddr, node_config: NodeConfigCached) -> Result<(), Error> {
|
async fn events_conn_handler(
|
||||||
|
stream: TcpStream,
|
||||||
|
addr: SocketAddr,
|
||||||
|
scyqueue: Option<&ScyllaQueue>,
|
||||||
|
ncc: NodeConfigCached,
|
||||||
|
) -> Result<(), Error> {
|
||||||
let (netin, netout) = stream.into_split();
|
let (netin, netout) = stream.into_split();
|
||||||
let inp = Box::new(TcpReadAsBytes::new(netin));
|
let inp = Box::new(TcpReadAsBytes::new(netin));
|
||||||
let span1 = span!(Level::INFO, "events_conn_handler");
|
let span1 = span!(Level::INFO, "events_conn_handler");
|
||||||
let r = events_conn_handler_inner(inp, netout, addr, &node_config)
|
let r = events_conn_handler_inner(inp, netout, addr, scyqueue, &ncc)
|
||||||
.instrument(span1)
|
.instrument(span1)
|
||||||
.await;
|
.await;
|
||||||
match r {
|
match r {
|
||||||
|
|||||||
@@ -88,7 +88,8 @@ fn raw_data_00() {
|
|||||||
let frame1 = Frame1Parts::new(qu.clone());
|
let frame1 = Frame1Parts::new(qu.clone());
|
||||||
let query = EventQueryJsonStringFrame(serde_json::to_string(&frame1).unwrap());
|
let query = EventQueryJsonStringFrame(serde_json::to_string(&frame1).unwrap());
|
||||||
let frame = sitem_data(query).make_frame()?;
|
let frame = sitem_data(query).make_frame()?;
|
||||||
let jh = taskrun::spawn(events_conn_handler(client, addr, cfg));
|
let scyqueue = err::todoval();
|
||||||
|
let jh = taskrun::spawn(events_conn_handler(client, addr, scyqueue, cfg));
|
||||||
con.write_all(&frame).await.unwrap();
|
con.write_all(&frame).await.unwrap();
|
||||||
eprintln!("written");
|
eprintln!("written");
|
||||||
con.shutdown().await.unwrap();
|
con.shutdown().await.unwrap();
|
||||||
|
|||||||
@@ -7,23 +7,20 @@ use items_0::streamitem::StreamItem;
|
|||||||
use items_2::channelevents::ChannelEvents;
|
use items_2::channelevents::ChannelEvents;
|
||||||
use netpod::log::*;
|
use netpod::log::*;
|
||||||
use netpod::ChConf;
|
use netpod::ChConf;
|
||||||
use netpod::NodeConfigCached;
|
|
||||||
use netpod::ScyllaConfig;
|
|
||||||
use query::api4::events::EventsSubQuery;
|
use query::api4::events::EventsSubQuery;
|
||||||
|
use scyllaconn::worker::ScyllaQueue;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use taskrun::tokio;
|
use taskrun::tokio;
|
||||||
|
|
||||||
pub async fn scylla_channel_event_stream(
|
pub async fn scylla_channel_event_stream(
|
||||||
evq: EventsSubQuery,
|
evq: EventsSubQuery,
|
||||||
chconf: ChConf,
|
chconf: ChConf,
|
||||||
scyco: &ScyllaConfig,
|
scyqueue: &ScyllaQueue,
|
||||||
_ncc: &NodeConfigCached,
|
|
||||||
) -> Result<Pin<Box<dyn Stream<Item = Sitemty<ChannelEvents>> + Send>>, Error> {
|
) -> Result<Pin<Box<dyn Stream<Item = Sitemty<ChannelEvents>> + Send>>, Error> {
|
||||||
// TODO depends in general on the query
|
// TODO depends in general on the query
|
||||||
// TODO why both in PlainEventsQuery and as separate parameter? Check other usages.
|
// TODO why both in PlainEventsQuery and as separate parameter? Check other usages.
|
||||||
|
// let do_one_before_range = evq.need_one_before_range();
|
||||||
let do_one_before_range = false;
|
let do_one_before_range = false;
|
||||||
// TODO use better builder pattern with shortcuts for production and dev defaults
|
|
||||||
let scy = scyllaconn::conn::create_scy_session(scyco).await?;
|
|
||||||
let series = chconf.series();
|
let series = chconf.series();
|
||||||
let scalar_type = chconf.scalar_type();
|
let scalar_type = chconf.scalar_type();
|
||||||
let shape = chconf.shape();
|
let shape = chconf.shape();
|
||||||
@@ -37,7 +34,7 @@ pub async fn scylla_channel_event_stream(
|
|||||||
scalar_type.clone(),
|
scalar_type.clone(),
|
||||||
shape.clone(),
|
shape.clone(),
|
||||||
with_values,
|
with_values,
|
||||||
scy,
|
scyqueue.clone(),
|
||||||
do_test_stream_error,
|
do_test_stream_error,
|
||||||
);
|
);
|
||||||
let stream = stream
|
let stream = stream
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use crate::errconv::ErrConv;
|
use crate::errconv::ErrConv;
|
||||||
use crate::events::EventsStreamScylla;
|
|
||||||
use err::Error;
|
use err::Error;
|
||||||
use futures_util::Future;
|
use futures_util::Future;
|
||||||
use futures_util::Stream;
|
use futures_util::Stream;
|
||||||
|
|||||||
+236
-104
@@ -1,5 +1,6 @@
|
|||||||
use crate::errconv::ErrConv;
|
use crate::errconv::ErrConv;
|
||||||
use crate::range::ScyllaSeriesRange;
|
use crate::range::ScyllaSeriesRange;
|
||||||
|
use crate::worker::ScyllaQueue;
|
||||||
use err::Error;
|
use err::Error;
|
||||||
use futures_util::Future;
|
use futures_util::Future;
|
||||||
use futures_util::FutureExt;
|
use futures_util::FutureExt;
|
||||||
@@ -20,7 +21,10 @@ use netpod::Shape;
|
|||||||
use netpod::TsMs;
|
use netpod::TsMs;
|
||||||
use netpod::TsNano;
|
use netpod::TsNano;
|
||||||
use scylla::frame::response::result::Row;
|
use scylla::frame::response::result::Row;
|
||||||
|
use scylla::prepared_statement::PreparedStatement;
|
||||||
|
use scylla::Session;
|
||||||
use scylla::Session as ScySession;
|
use scylla::Session as ScySession;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
@@ -28,61 +32,131 @@ use std::sync::Arc;
|
|||||||
use std::task::Context;
|
use std::task::Context;
|
||||||
use std::task::Poll;
|
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,
|
series: u64,
|
||||||
range: ScyllaSeriesRange,
|
range: ScyllaSeriesRange,
|
||||||
scy: Arc<ScySession>,
|
stmts: &StmtsEventsRt,
|
||||||
|
scy: &ScySession,
|
||||||
) -> Result<(VecDeque<TsMs>, VecDeque<TsMs>), Error> {
|
) -> Result<(VecDeque<TsMs>, VecDeque<TsMs>), Error> {
|
||||||
trace!("find_ts_msp series {:?} {:?}", series, range);
|
trace!("find_ts_msp series {:?} {:?}", series, range);
|
||||||
let mut ret1 = VecDeque::new();
|
let mut ret1 = VecDeque::new();
|
||||||
let mut ret2 = 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);
|
let params = (series as i64, range.beg().ms() as i64);
|
||||||
trace!("find_ts_msp query 1 params {:?}", params);
|
trace!("find_ts_msp query 1 params {:?}", params);
|
||||||
let res = scy.query(cql, params).await.err_conv()?;
|
let mut res = scy
|
||||||
for row in res.rows_typed_or_empty::<(i64,)>() {
|
.execute_iter(stmts.ts_msp_bck.clone(), params)
|
||||||
let row = row.err_conv()?;
|
.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);
|
let ts = TsMs::from_ms_u64(row.0 as u64);
|
||||||
trace!("query 1 ts_msp {}", ts);
|
trace!("query 1 ts_msp {}", ts);
|
||||||
ret1.push_front(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);
|
let params = (series as i64, range.beg().ms() as i64, 1 + range.end().ms() as i64);
|
||||||
trace!("find_ts_msp query 2 params {:?}", params);
|
trace!("find_ts_msp query 2 params {:?}", params);
|
||||||
let res = scy.query(cql, params).await.err_conv()?;
|
let mut res = scy
|
||||||
for row in res.rows_typed_or_empty::<(i64,)>() {
|
.execute_iter(stmts.ts_msp_fwd.clone(), params)
|
||||||
let row = row.err_conv()?;
|
.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);
|
let ts = TsMs::from_ms_u64(row.0 as u64);
|
||||||
trace!("query 2 ts_msp {}", ts);
|
trace!("query 2 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);
|
|
||||||
}
|
}
|
||||||
|
// 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());
|
trace!("find_ts_msp n1 {:?} n2 {:?}", ret1.len(), ret2.len());
|
||||||
Ok((ret1, ret2))
|
Ok((ret1, ret2))
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ValTy: Sized {
|
trait ValTy: Sized + 'static {
|
||||||
type ScaTy: ScalarOps + std::default::Default;
|
type ScaTy: ScalarOps + std::default::Default;
|
||||||
type ScyTy: scylla::cql_to_rust::FromCqlVal<scylla::frame::response::result::CqlValue>;
|
type ScyTy: scylla::cql_to_rust::FromCqlVal<scylla::frame::response::result::CqlValue>;
|
||||||
type Container: Events + Appendable<Self>;
|
type Container: Events + Appendable<Self>;
|
||||||
fn from_scyty(inp: Self::ScyTy) -> Self;
|
fn from_scyty(inp: Self::ScyTy) -> Self;
|
||||||
|
fn from_valueblob(inp: Vec<u8>) -> Self;
|
||||||
fn table_name() -> &'static str;
|
fn table_name() -> &'static str;
|
||||||
fn default() -> Self;
|
fn default() -> Self;
|
||||||
fn is_valueblob() -> bool;
|
fn is_valueblob() -> bool;
|
||||||
|
fn st_name() -> &'static str;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_scaty_scalar {
|
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 {
|
impl ValTy for $st {
|
||||||
type ScaTy = $st;
|
type ScaTy = $st;
|
||||||
type ScyTy = $st_scy;
|
type ScyTy = $st_scy;
|
||||||
@@ -90,6 +164,9 @@ macro_rules! impl_scaty_scalar {
|
|||||||
fn from_scyty(inp: Self::ScyTy) -> Self {
|
fn from_scyty(inp: Self::ScyTy) -> Self {
|
||||||
inp as Self
|
inp as Self
|
||||||
}
|
}
|
||||||
|
fn from_valueblob(_inp: Vec<u8>) -> Self {
|
||||||
|
<Self as ValTy>::default()
|
||||||
|
}
|
||||||
fn table_name() -> &'static str {
|
fn table_name() -> &'static str {
|
||||||
$table_name
|
$table_name
|
||||||
}
|
}
|
||||||
@@ -99,12 +176,15 @@ macro_rules! impl_scaty_scalar {
|
|||||||
fn is_valueblob() -> bool {
|
fn is_valueblob() -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
fn st_name() -> &'static str {
|
||||||
|
$st_name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_scaty_array {
|
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 {
|
impl ValTy for $vt {
|
||||||
type ScaTy = $st;
|
type ScaTy = $st;
|
||||||
type ScyTy = $st_scy;
|
type ScyTy = $st_scy;
|
||||||
@@ -112,6 +192,22 @@ macro_rules! impl_scaty_array {
|
|||||||
fn from_scyty(inp: Self::ScyTy) -> Self {
|
fn from_scyty(inp: Self::ScyTy) -> Self {
|
||||||
inp.into_iter().map(|x| x as Self::ScaTy).collect()
|
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 {
|
fn table_name() -> &'static str {
|
||||||
$table_name
|
$table_name
|
||||||
}
|
}
|
||||||
@@ -121,35 +217,38 @@ macro_rules! impl_scaty_array {
|
|||||||
fn is_valueblob() -> bool {
|
fn is_valueblob() -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
fn st_name() -> &'static str {
|
||||||
|
$st_name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_scaty_scalar!(u8, i8, "st_events_scalar_u8");
|
impl_scaty_scalar!(u8, i8, "u8", "st_events_scalar_u8");
|
||||||
impl_scaty_scalar!(u16, i16, "st_events_scalar_u16");
|
impl_scaty_scalar!(u16, i16, "u16", "st_events_scalar_u16");
|
||||||
impl_scaty_scalar!(u32, i32, "st_events_scalar_u32");
|
impl_scaty_scalar!(u32, i32, "u32", "st_events_scalar_u32");
|
||||||
impl_scaty_scalar!(u64, i64, "st_events_scalar_u64");
|
impl_scaty_scalar!(u64, i64, "u64", "st_events_scalar_u64");
|
||||||
impl_scaty_scalar!(i8, i8, "st_events_scalar_i8");
|
impl_scaty_scalar!(i8, i8, "i8", "st_events_scalar_i8");
|
||||||
impl_scaty_scalar!(i16, i16, "st_events_scalar_i16");
|
impl_scaty_scalar!(i16, i16, "i16", "st_events_scalar_i16");
|
||||||
impl_scaty_scalar!(i32, i32, "st_events_scalar_i32");
|
impl_scaty_scalar!(i32, i32, "i32", "st_events_scalar_i32");
|
||||||
impl_scaty_scalar!(i64, i64, "st_events_scalar_i64");
|
impl_scaty_scalar!(i64, i64, "i64", "st_events_scalar_i64");
|
||||||
impl_scaty_scalar!(f32, f32, "st_events_scalar_f32");
|
impl_scaty_scalar!(f32, f32, "f32", "st_events_scalar_f32");
|
||||||
impl_scaty_scalar!(f64, f64, "st_events_scalar_f64");
|
impl_scaty_scalar!(f64, f64, "f64", "st_events_scalar_f64");
|
||||||
impl_scaty_scalar!(bool, bool, "st_events_scalar_bool");
|
impl_scaty_scalar!(bool, bool, "bool", "st_events_scalar_bool");
|
||||||
impl_scaty_scalar!(String, String, "st_events_scalar_string");
|
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<u8>, u8, Vec<i8>, "u8", "st_events_array_u8");
|
||||||
impl_scaty_array!(Vec<u16>, u16, Vec<i16>, "st_events_array_u16");
|
impl_scaty_array!(Vec<u16>, u16, Vec<i16>, "u16", "st_events_array_u16");
|
||||||
impl_scaty_array!(Vec<u32>, u32, Vec<i32>, "st_events_array_u32");
|
impl_scaty_array!(Vec<u32>, u32, Vec<i32>, "u32", "st_events_array_u32");
|
||||||
impl_scaty_array!(Vec<u64>, u64, Vec<i64>, "st_events_array_u64");
|
impl_scaty_array!(Vec<u64>, u64, Vec<i64>, "u64", "st_events_array_u64");
|
||||||
impl_scaty_array!(Vec<i8>, i8, Vec<i8>, "st_events_array_i8");
|
impl_scaty_array!(Vec<i8>, i8, Vec<i8>, "i8", "st_events_array_i8");
|
||||||
impl_scaty_array!(Vec<i16>, i16, Vec<i16>, "st_events_array_i16");
|
impl_scaty_array!(Vec<i16>, i16, Vec<i16>, "i16", "st_events_array_i16");
|
||||||
impl_scaty_array!(Vec<i32>, i32, Vec<i32>, "st_events_array_i32");
|
impl_scaty_array!(Vec<i32>, i32, Vec<i32>, "i32", "st_events_array_i32");
|
||||||
impl_scaty_array!(Vec<i64>, i64, Vec<i64>, "st_events_array_i64");
|
impl_scaty_array!(Vec<i64>, i64, Vec<i64>, "i64", "st_events_array_i64");
|
||||||
impl_scaty_array!(Vec<f32>, f32, Vec<f32>, "st_events_array_f32");
|
impl_scaty_array!(Vec<f32>, f32, Vec<f32>, "f32", "st_events_array_f32");
|
||||||
impl_scaty_array!(Vec<f64>, f64, Vec<f64>, "st_events_array_f64");
|
impl_scaty_array!(Vec<f64>, f64, Vec<f64>, "f64", "st_events_array_f64");
|
||||||
impl_scaty_array!(Vec<bool>, bool, Vec<bool>, "st_events_array_bool");
|
impl_scaty_array!(Vec<bool>, bool, Vec<bool>, "bool", "st_events_array_bool");
|
||||||
impl_scaty_array!(Vec<String>, String, Vec<String>, "st_events_array_string");
|
// impl_scaty_array!(Vec<String>, String, Vec<String>, "string", "st_events_array_string");
|
||||||
|
|
||||||
struct ReadNextValuesOpts {
|
struct ReadNextValuesOpts {
|
||||||
series: u64,
|
series: u64,
|
||||||
@@ -157,33 +256,40 @@ struct ReadNextValuesOpts {
|
|||||||
range: ScyllaSeriesRange,
|
range: ScyllaSeriesRange,
|
||||||
fwd: bool,
|
fwd: bool,
|
||||||
with_values: bool,
|
with_values: bool,
|
||||||
scy: Arc<ScySession>,
|
scyqueue: ScyllaQueue,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn read_next_values<ST>(opts: ReadNextValuesOpts) -> Result<Box<dyn Events>, Error>
|
async fn read_next_values<ST>(opts: ReadNextValuesOpts) -> Result<Box<dyn Events>, Error>
|
||||||
where
|
where
|
||||||
ST: ValTy,
|
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 series = opts.series;
|
||||||
let ts_msp = opts.ts_msp;
|
let ts_msp = opts.ts_msp;
|
||||||
let range = opts.range;
|
let range = opts.range;
|
||||||
let fwd = opts.fwd;
|
|
||||||
let scy = opts.scy;
|
|
||||||
let table_name = ST::table_name();
|
let table_name = ST::table_name();
|
||||||
if range.end() > TsNano::from_ns(i64::MAX as u64) {
|
if range.end() > TsNano::from_ns(i64::MAX as u64) {
|
||||||
return Err(Error::with_msg_no_trace(format!("range.end overflows i64")));
|
return Err(Error::with_msg_no_trace(format!("range.end overflows i64")));
|
||||||
}
|
}
|
||||||
let cql_fields = if opts.with_values {
|
let ret = if opts.fwd {
|
||||||
if ST::is_valueblob() {
|
|
||||||
"ts_lsp, pulse, valueblob"
|
|
||||||
} else {
|
|
||||||
"ts_lsp, pulse, value"
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
"ts_lsp, pulse"
|
|
||||||
};
|
|
||||||
let ret = if fwd {
|
|
||||||
let ts_lsp_min = if range.beg() > ts_msp.ns() {
|
let ts_lsp_min = if range.beg() > ts_msp.ns() {
|
||||||
range.beg().delta(ts_msp.ns())
|
range.beg().delta(ts_msp.ns())
|
||||||
} else {
|
} else {
|
||||||
@@ -201,14 +307,20 @@ where
|
|||||||
ts_lsp_max,
|
ts_lsp_max,
|
||||||
table_name,
|
table_name,
|
||||||
);
|
);
|
||||||
// TODO use prepared!
|
let qu_name = if opts.with_values {
|
||||||
let cql = format!(
|
if ST::is_valueblob() {
|
||||||
concat!(
|
format!("array_{}_valueblobs_fwd", ST::st_name())
|
||||||
"select {} from {}",
|
} else {
|
||||||
" where series = ? and ts_msp = ? and ts_lsp >= ? and ts_lsp < ?"
|
format!("array_{}_values_fwd", ST::st_name())
|
||||||
),
|
}
|
||||||
cql_fields, table_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 = (
|
let params = (
|
||||||
series as i64,
|
series as i64,
|
||||||
ts_msp.ms() as i64,
|
ts_msp.ms() as i64,
|
||||||
@@ -216,13 +328,13 @@ where
|
|||||||
ts_lsp_max.ns() as i64,
|
ts_lsp_max.ns() as i64,
|
||||||
);
|
);
|
||||||
trace!("FWD event search params {:?}", params);
|
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();
|
let mut rows = Vec::new();
|
||||||
while let Some(x) = res.next().await {
|
while let Some(x) = res.next().await {
|
||||||
rows.push(x.err_conv()?);
|
rows.push(x.err_conv()?);
|
||||||
}
|
}
|
||||||
let mut last_before = None;
|
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
|
ret
|
||||||
} else {
|
} else {
|
||||||
let ts_lsp_max = if ts_msp.ns() < range.beg() {
|
let ts_lsp_max = if ts_msp.ns() < range.beg() {
|
||||||
@@ -231,23 +343,29 @@ where
|
|||||||
DtNano::from_ns(0)
|
DtNano::from_ns(0)
|
||||||
};
|
};
|
||||||
trace!("BCK ts_msp {} ts_lsp_max {} {}", ts_msp, ts_lsp_max, table_name,);
|
trace!("BCK ts_msp {} ts_lsp_max {} {}", ts_msp, ts_lsp_max, table_name,);
|
||||||
// TODO use prepared!
|
let qu_name = if opts.with_values {
|
||||||
let cql = format!(
|
if ST::is_valueblob() {
|
||||||
concat!(
|
format!("array_{}_valueblobs_bck", ST::st_name())
|
||||||
"select {} from {}",
|
} else {
|
||||||
" where series = ? and ts_msp = ? and ts_lsp < ? order by ts_lsp desc limit 1"
|
format!("array_{}_values_bck", ST::st_name())
|
||||||
),
|
}
|
||||||
cql_fields, table_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);
|
let params = (series as i64, ts_msp.ms() as i64, ts_lsp_max.ns() as i64);
|
||||||
trace!("BCK event search params {:?}", params);
|
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();
|
let mut rows = Vec::new();
|
||||||
while let Some(x) = res.next().await {
|
while let Some(x) = res.next().await {
|
||||||
rows.push(x.err_conv()?);
|
rows.push(x.err_conv()?);
|
||||||
}
|
}
|
||||||
let mut _last_before = None;
|
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 {
|
if ret.len() > 1 {
|
||||||
error!("multiple events in backwards search {}", ret.len());
|
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());
|
trace!("read a value blob len {}", row.2.len());
|
||||||
let ts = TsNano::from_ns(ts_msp.ns_u64() + row.0 as u64);
|
let ts = TsNano::from_ns(ts_msp.ns_u64() + row.0 as u64);
|
||||||
let pulse = row.1 as u64;
|
let pulse = row.1 as u64;
|
||||||
let value = ValTy::default();
|
let value = ValTy::from_valueblob(row.2);
|
||||||
(ts, pulse, value)
|
(ts, pulse, value)
|
||||||
} else {
|
} else {
|
||||||
let row: (i64, i64, ST::ScyTy) = row.into_typed().err_conv()?;
|
let row: (i64, i64, ST::ScyTy) = row.into_typed().err_conv()?;
|
||||||
@@ -326,7 +444,7 @@ struct ReadValues {
|
|||||||
with_values: bool,
|
with_values: bool,
|
||||||
fut: Pin<Box<dyn Future<Output = Result<Box<dyn Events>, Error>> + Send>>,
|
fut: Pin<Box<dyn Future<Output = Result<Box<dyn Events>, Error>> + Send>>,
|
||||||
fut_done: bool,
|
fut_done: bool,
|
||||||
scy: Arc<ScySession>,
|
scyqueue: ScyllaQueue,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadValues {
|
impl ReadValues {
|
||||||
@@ -338,7 +456,7 @@ impl ReadValues {
|
|||||||
ts_msps: VecDeque<TsMs>,
|
ts_msps: VecDeque<TsMs>,
|
||||||
fwd: bool,
|
fwd: bool,
|
||||||
with_values: bool,
|
with_values: bool,
|
||||||
scy: Arc<ScySession>,
|
scyqueue: ScyllaQueue,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut ret = Self {
|
let mut ret = Self {
|
||||||
series,
|
series,
|
||||||
@@ -352,7 +470,7 @@ impl ReadValues {
|
|||||||
"future not initialized",
|
"future not initialized",
|
||||||
)))),
|
)))),
|
||||||
fut_done: false,
|
fut_done: false,
|
||||||
scy,
|
scyqueue,
|
||||||
};
|
};
|
||||||
ret.next();
|
ret.next();
|
||||||
ret
|
ret
|
||||||
@@ -375,7 +493,7 @@ impl ReadValues {
|
|||||||
range: self.range.clone(),
|
range: self.range.clone(),
|
||||||
fwd: self.fwd,
|
fwd: self.fwd,
|
||||||
with_values: self.with_values,
|
with_values: self.with_values,
|
||||||
scy: self.scy.clone(),
|
scyqueue: self.scyqueue.clone(),
|
||||||
};
|
};
|
||||||
let scalar_type = self.scalar_type.clone();
|
let scalar_type = self.scalar_type.clone();
|
||||||
let shape = self.shape.clone();
|
let shape = self.shape.clone();
|
||||||
@@ -394,8 +512,8 @@ impl ReadValues {
|
|||||||
ScalarType::F64 => read_next_values::<f64>(opts).await,
|
ScalarType::F64 => read_next_values::<f64>(opts).await,
|
||||||
ScalarType::BOOL => read_next_values::<bool>(opts).await,
|
ScalarType::BOOL => read_next_values::<bool>(opts).await,
|
||||||
ScalarType::STRING => read_next_values::<String>(opts).await,
|
ScalarType::STRING => read_next_values::<String>(opts).await,
|
||||||
_ => {
|
ScalarType::ChannelStatus => {
|
||||||
error!("TODO ReadValues add more types");
|
warn!("read scalar channel status not yet supported");
|
||||||
err::todoval()
|
err::todoval()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -411,8 +529,12 @@ impl ReadValues {
|
|||||||
ScalarType::F32 => read_next_values::<Vec<f32>>(opts).await,
|
ScalarType::F32 => read_next_values::<Vec<f32>>(opts).await,
|
||||||
ScalarType::F64 => read_next_values::<Vec<f64>>(opts).await,
|
ScalarType::F64 => read_next_values::<Vec<f64>>(opts).await,
|
||||||
ScalarType::BOOL => read_next_values::<Vec<bool>>(opts).await,
|
ScalarType::BOOL => read_next_values::<Vec<bool>>(opts).await,
|
||||||
_ => {
|
ScalarType::STRING => {
|
||||||
error!("TODO ReadValues add more types");
|
warn!("read array string not yet supported");
|
||||||
|
err::todoval()
|
||||||
|
}
|
||||||
|
ScalarType::ChannelStatus => {
|
||||||
|
warn!("read array channel status not yet supported");
|
||||||
err::todoval()
|
err::todoval()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -428,7 +550,7 @@ impl ReadValues {
|
|||||||
|
|
||||||
enum FrState {
|
enum FrState {
|
||||||
New,
|
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),
|
ReadBack1(ReadValues),
|
||||||
ReadBack2(ReadValues),
|
ReadBack2(ReadValues),
|
||||||
ReadValues(ReadValues),
|
ReadValues(ReadValues),
|
||||||
@@ -445,7 +567,7 @@ pub struct EventsStreamScylla {
|
|||||||
do_one_before_range: bool,
|
do_one_before_range: bool,
|
||||||
ts_msp_bck: VecDeque<TsMs>,
|
ts_msp_bck: VecDeque<TsMs>,
|
||||||
ts_msp_fwd: VecDeque<TsMs>,
|
ts_msp_fwd: VecDeque<TsMs>,
|
||||||
scy: Arc<ScySession>,
|
scyqueue: ScyllaQueue,
|
||||||
do_test_stream_error: bool,
|
do_test_stream_error: bool,
|
||||||
found_one_after: bool,
|
found_one_after: bool,
|
||||||
with_values: bool,
|
with_values: bool,
|
||||||
@@ -460,7 +582,7 @@ impl EventsStreamScylla {
|
|||||||
scalar_type: ScalarType,
|
scalar_type: ScalarType,
|
||||||
shape: Shape,
|
shape: Shape,
|
||||||
with_values: bool,
|
with_values: bool,
|
||||||
scy: Arc<ScySession>,
|
scyqueue: ScyllaQueue,
|
||||||
do_test_stream_error: bool,
|
do_test_stream_error: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
debug!("EventsStreamScylla::new");
|
debug!("EventsStreamScylla::new");
|
||||||
@@ -473,7 +595,7 @@ impl EventsStreamScylla {
|
|||||||
do_one_before_range,
|
do_one_before_range,
|
||||||
ts_msp_bck: VecDeque::new(),
|
ts_msp_bck: VecDeque::new(),
|
||||||
ts_msp_fwd: VecDeque::new(),
|
ts_msp_fwd: VecDeque::new(),
|
||||||
scy,
|
scyqueue,
|
||||||
do_test_stream_error,
|
do_test_stream_error,
|
||||||
found_one_after: false,
|
found_one_after: false,
|
||||||
with_values,
|
with_values,
|
||||||
@@ -505,7 +627,7 @@ impl EventsStreamScylla {
|
|||||||
[msp].into(),
|
[msp].into(),
|
||||||
false,
|
false,
|
||||||
self.with_values,
|
self.with_values,
|
||||||
self.scy.clone(),
|
self.scyqueue.clone(),
|
||||||
);
|
);
|
||||||
self.state = FrState::ReadBack1(st);
|
self.state = FrState::ReadBack1(st);
|
||||||
} else if self.ts_msp_fwd.len() > 0 {
|
} else if self.ts_msp_fwd.len() > 0 {
|
||||||
@@ -518,7 +640,7 @@ impl EventsStreamScylla {
|
|||||||
mem::replace(&mut self.ts_msp_fwd, VecDeque::new()),
|
mem::replace(&mut self.ts_msp_fwd, VecDeque::new()),
|
||||||
true,
|
true,
|
||||||
self.with_values,
|
self.with_values,
|
||||||
self.scy.clone(),
|
self.scyqueue.clone(),
|
||||||
);
|
);
|
||||||
self.state = FrState::ReadValues(st);
|
self.state = FrState::ReadValues(st);
|
||||||
} else {
|
} else {
|
||||||
@@ -539,7 +661,7 @@ impl EventsStreamScylla {
|
|||||||
mem::replace(&mut self.ts_msp_fwd, VecDeque::new()),
|
mem::replace(&mut self.ts_msp_fwd, VecDeque::new()),
|
||||||
true,
|
true,
|
||||||
self.with_values,
|
self.with_values,
|
||||||
self.scy.clone(),
|
self.scyqueue.clone(),
|
||||||
);
|
);
|
||||||
self.state = FrState::ReadValues(st);
|
self.state = FrState::ReadValues(st);
|
||||||
} else {
|
} else {
|
||||||
@@ -556,7 +678,7 @@ impl EventsStreamScylla {
|
|||||||
[msp].into(),
|
[msp].into(),
|
||||||
false,
|
false,
|
||||||
self.with_values,
|
self.with_values,
|
||||||
self.scy.clone(),
|
self.scyqueue.clone(),
|
||||||
);
|
);
|
||||||
self.state = FrState::ReadBack2(st);
|
self.state = FrState::ReadBack2(st);
|
||||||
} else if self.ts_msp_fwd.len() > 0 {
|
} else if self.ts_msp_fwd.len() > 0 {
|
||||||
@@ -569,7 +691,7 @@ impl EventsStreamScylla {
|
|||||||
mem::replace(&mut self.ts_msp_fwd, VecDeque::new()),
|
mem::replace(&mut self.ts_msp_fwd, VecDeque::new()),
|
||||||
true,
|
true,
|
||||||
self.with_values,
|
self.with_values,
|
||||||
self.scy.clone(),
|
self.scyqueue.clone(),
|
||||||
);
|
);
|
||||||
self.state = FrState::ReadValues(st);
|
self.state = FrState::ReadValues(st);
|
||||||
} else {
|
} else {
|
||||||
@@ -593,7 +715,7 @@ impl EventsStreamScylla {
|
|||||||
mem::replace(&mut self.ts_msp_fwd, VecDeque::new()),
|
mem::replace(&mut self.ts_msp_fwd, VecDeque::new()),
|
||||||
true,
|
true,
|
||||||
self.with_values,
|
self.with_values,
|
||||||
self.scy.clone(),
|
self.scyqueue.clone(),
|
||||||
);
|
);
|
||||||
self.state = FrState::ReadValues(st);
|
self.state = FrState::ReadValues(st);
|
||||||
} else {
|
} 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 {
|
impl Stream for EventsStreamScylla {
|
||||||
type Item = Result<ChannelEvents, Error>;
|
type Item = Result<ChannelEvents, Error>;
|
||||||
|
|
||||||
@@ -620,7 +750,9 @@ impl Stream for EventsStreamScylla {
|
|||||||
}
|
}
|
||||||
break match self.state {
|
break match self.state {
|
||||||
FrState::New => {
|
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);
|
let fut = Box::pin(fut);
|
||||||
self.state = FrState::FindMsp(fut);
|
self.state = FrState::FindMsp(fut);
|
||||||
continue;
|
continue;
|
||||||
@@ -633,7 +765,7 @@ impl Stream for EventsStreamScylla {
|
|||||||
Ready(Err(e)) => {
|
Ready(Err(e)) => {
|
||||||
error!("EventsStreamScylla FindMsp {e}");
|
error!("EventsStreamScylla FindMsp {e}");
|
||||||
self.state = FrState::DataDone;
|
self.state = FrState::DataDone;
|
||||||
Ready(Some(Err(e)))
|
Ready(Some(Err(e.into())))
|
||||||
}
|
}
|
||||||
Pending => Pending,
|
Pending => Pending,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
use crate::conn::create_scy_session_no_ks;
|
use crate::conn::create_scy_session_no_ks;
|
||||||
|
use crate::events::StmtsEventsRt;
|
||||||
|
use crate::range::ScyllaSeriesRange;
|
||||||
use async_channel::Receiver;
|
use async_channel::Receiver;
|
||||||
use async_channel::Sender;
|
use async_channel::Sender;
|
||||||
use err::thiserror;
|
use err::thiserror;
|
||||||
use err::ThisError;
|
use err::ThisError;
|
||||||
|
use futures_util::Future;
|
||||||
|
use items_0::Events;
|
||||||
use netpod::log::*;
|
use netpod::log::*;
|
||||||
use netpod::range::evrange::NanoRange;
|
|
||||||
use netpod::ScyllaConfig;
|
use netpod::ScyllaConfig;
|
||||||
|
use netpod::TsMs;
|
||||||
use scylla::Session;
|
use scylla::Session;
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
use std::fmt;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Debug, ThisError)]
|
#[derive(Debug, ThisError)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@@ -24,7 +32,31 @@ impl err::ToErr for Error {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Job {
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -33,31 +65,59 @@ pub struct ScyllaQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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 (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)?;
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct ScyllaWorker {
|
pub struct ScyllaWorker {
|
||||||
rx: Receiver<Job>,
|
rx: Receiver<Job>,
|
||||||
scy: Session,
|
scy: Arc<Session>,
|
||||||
// pgjh: Option<JoinHandle<Result<(), err::Error>>>,
|
stmts_st: Arc<StmtsEventsRt>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScyllaWorker {
|
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 (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 queue = ScyllaQueue { tx };
|
||||||
let worker = Self {
|
let worker = Self { rx, scy, stmts_st };
|
||||||
rx,
|
|
||||||
scy,
|
|
||||||
// pgjh: Some(pgjh),
|
|
||||||
};
|
|
||||||
Ok((queue, worker))
|
Ok((queue, worker))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,12 +132,19 @@ impl ScyllaWorker {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
match job {
|
match job {
|
||||||
Job::JobA(backend, tx) => {
|
Job::FindTsMsp(series, range, tx) => {
|
||||||
let res = Ok::<_, Error>(backend);
|
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() {
|
if tx.send(res.map_err(Into::into)).await.is_err() {
|
||||||
// TODO count for stats
|
// 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