Reduce pg conn create, move lookup into worker mod
This commit is contained in:
@@ -204,38 +204,3 @@ pub enum FindChannelError {
|
|||||||
MultipleFound,
|
MultipleFound,
|
||||||
Database(String),
|
Database(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
// On sf-databuffer, the channel name identifies the series. But we can also have a series id.
|
|
||||||
// This function is used if the request provides only the series-id, but no name.
|
|
||||||
pub async fn find_sf_channel_by_series(
|
|
||||||
channel: SfDbChannel,
|
|
||||||
pgclient: Arc<PgClient>,
|
|
||||||
) -> Result<SfDbChannel, FindChannelError> {
|
|
||||||
debug!("find_sf_channel_by_series {:?}", channel);
|
|
||||||
let series = channel.series().ok_or_else(|| FindChannelError::BadSeriesId)?;
|
|
||||||
let sql = "select rowid from facilities where name = $1";
|
|
||||||
let rows = pgclient
|
|
||||||
.query(sql, &[&channel.backend()])
|
|
||||||
.await
|
|
||||||
.map_err(|e| FindChannelError::Database(e.to_string()))?;
|
|
||||||
let row = rows
|
|
||||||
.into_iter()
|
|
||||||
.next()
|
|
||||||
.ok_or_else(|| FindChannelError::UnknownBackend)?;
|
|
||||||
let backend_id: i64 = row.get(0);
|
|
||||||
let sql = "select name from channels where facility = $1 and rowid = $2";
|
|
||||||
let rows = pgclient
|
|
||||||
.query(sql, &[&backend_id, &(series as i64)])
|
|
||||||
.await
|
|
||||||
.map_err(|e| FindChannelError::Database(e.to_string()))?;
|
|
||||||
if rows.len() > 1 {
|
|
||||||
return Err(FindChannelError::MultipleFound);
|
|
||||||
}
|
|
||||||
if let Some(row) = rows.into_iter().next() {
|
|
||||||
let name = row.get::<_, String>(0);
|
|
||||||
let channel = SfDbChannel::from_full(channel.backend(), channel.series(), name);
|
|
||||||
Ok(channel)
|
|
||||||
} else {
|
|
||||||
return Err(FindChannelError::NoFound);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use netpod::ChConf;
|
|||||||
use netpod::ChannelSearchQuery;
|
use netpod::ChannelSearchQuery;
|
||||||
use netpod::ChannelSearchResult;
|
use netpod::ChannelSearchResult;
|
||||||
use netpod::Database;
|
use netpod::Database;
|
||||||
|
use netpod::SfDbChannel;
|
||||||
use taskrun::tokio;
|
use taskrun::tokio;
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
use tokio_postgres::Client;
|
use tokio_postgres::Client;
|
||||||
@@ -44,6 +45,10 @@ enum Job {
|
|||||||
Sender<Result<Vec<Option<crate::channelinfo::ChannelInfo>>, crate::channelinfo::Error>>,
|
Sender<Result<Vec<Option<crate::channelinfo::ChannelInfo>>, crate::channelinfo::Error>>,
|
||||||
),
|
),
|
||||||
SearchChannel(ChannelSearchQuery, Sender<Result<ChannelSearchResult, err::Error>>),
|
SearchChannel(ChannelSearchQuery, Sender<Result<ChannelSearchResult, err::Error>>),
|
||||||
|
SfChannelBySeries(
|
||||||
|
netpod::SfDbChannel,
|
||||||
|
Sender<Result<netpod::SfDbChannel, crate::FindChannelError>>,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -63,7 +68,7 @@ impl PgQueue {
|
|||||||
Ok(rx)
|
Ok(rx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn chconf_best_matching_name_range_job(
|
pub async fn chconf_best_matching_name_range(
|
||||||
&self,
|
&self,
|
||||||
backend: &str,
|
backend: &str,
|
||||||
name: &str,
|
name: &str,
|
||||||
@@ -95,6 +100,17 @@ impl PgQueue {
|
|||||||
let ret = rx.recv().await?;
|
let ret = rx.recv().await?;
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn find_sf_channel_by_series(
|
||||||
|
&self,
|
||||||
|
query: netpod::SfDbChannel,
|
||||||
|
) -> Result<Result<netpod::SfDbChannel, crate::FindChannelError>, Error> {
|
||||||
|
let (tx, rx) = async_channel::bounded(1);
|
||||||
|
let job = Job::SfChannelBySeries(query, tx);
|
||||||
|
self.tx.send(job).await.map_err(|_| Error::ChannelSend)?;
|
||||||
|
let ret = rx.recv().await?;
|
||||||
|
Ok(ret)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -154,6 +170,12 @@ impl PgWorker {
|
|||||||
// TODO count for stats
|
// TODO count for stats
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Job::SfChannelBySeries(query, tx) => {
|
||||||
|
let res = find_sf_channel_by_series(query, &self.pg).await;
|
||||||
|
if tx.send(res.map_err(Into::into)).await.is_err() {
|
||||||
|
// TODO count for stats
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,3 +193,39 @@ impl PgWorker {
|
|||||||
self.rx.close();
|
self.rx.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On sf-databuffer, the channel name identifies the series. But we can also have a series id.
|
||||||
|
// This function is used if the request provides only the series-id, but no name.
|
||||||
|
async fn find_sf_channel_by_series(
|
||||||
|
channel: SfDbChannel,
|
||||||
|
pgclient: &Client,
|
||||||
|
) -> Result<SfDbChannel, crate::FindChannelError> {
|
||||||
|
use crate::FindChannelError;
|
||||||
|
debug!("find_sf_channel_by_series {:?}", channel);
|
||||||
|
let series = channel.series().ok_or_else(|| FindChannelError::BadSeriesId)?;
|
||||||
|
let sql = "select rowid from facilities where name = $1";
|
||||||
|
let rows = pgclient
|
||||||
|
.query(sql, &[&channel.backend()])
|
||||||
|
.await
|
||||||
|
.map_err(|e| FindChannelError::Database(e.to_string()))?;
|
||||||
|
let row = rows
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| FindChannelError::UnknownBackend)?;
|
||||||
|
let backend_id: i64 = row.get(0);
|
||||||
|
let sql = "select name from channels where facility = $1 and rowid = $2";
|
||||||
|
let rows = pgclient
|
||||||
|
.query(sql, &[&backend_id, &(series as i64)])
|
||||||
|
.await
|
||||||
|
.map_err(|e| FindChannelError::Database(e.to_string()))?;
|
||||||
|
if rows.len() > 1 {
|
||||||
|
return Err(FindChannelError::MultipleFound);
|
||||||
|
}
|
||||||
|
if let Some(row) = rows.into_iter().next() {
|
||||||
|
let name = row.get::<_, String>(0);
|
||||||
|
let channel = SfDbChannel::from_full(channel.backend(), channel.series(), name);
|
||||||
|
Ok(channel)
|
||||||
|
} else {
|
||||||
|
return Err(FindChannelError::NoFound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ use httpclient::StreamResponse;
|
|||||||
use httpclient::ToJsonBody;
|
use httpclient::ToJsonBody;
|
||||||
use netpod::log::*;
|
use netpod::log::*;
|
||||||
use netpod::req_uri_to_url;
|
use netpod::req_uri_to_url;
|
||||||
|
use netpod::ChannelTypeConfigGen;
|
||||||
use netpod::FromUrl;
|
use netpod::FromUrl;
|
||||||
use netpod::NodeConfigCached;
|
use netpod::NodeConfigCached;
|
||||||
use netpod::ReqCtx;
|
use netpod::ReqCtx;
|
||||||
@@ -87,12 +88,15 @@ async fn plain_events(
|
|||||||
pgqueue: &PgQueue,
|
pgqueue: &PgQueue,
|
||||||
ncc: &NodeConfigCached,
|
ncc: &NodeConfigCached,
|
||||||
) -> Result<StreamResponse, Error> {
|
) -> Result<StreamResponse, Error> {
|
||||||
|
let ch_conf = chconf_from_events_quorum(&evq, ctx, pgqueue, ncc)
|
||||||
|
.await?
|
||||||
|
.ok_or_else(|| Error::with_msg_no_trace("channel not found"))?;
|
||||||
if accepts_cbor_framed(req.headers()) {
|
if accepts_cbor_framed(req.headers()) {
|
||||||
Ok(plain_events_cbor_framed(req, evq, ctx, pgqueue, ncc).await?)
|
Ok(plain_events_cbor_framed(req, evq, ch_conf, ctx, ncc).await?)
|
||||||
} else if accepts_json_framed(req.headers()) {
|
} else if accepts_json_framed(req.headers()) {
|
||||||
Ok(plain_events_json_framed(req, evq, ctx, pgqueue, ncc).await?)
|
Ok(plain_events_json_framed(req, evq, ch_conf, ctx, ncc).await?)
|
||||||
} else if accepts_json_or_all(req.headers()) {
|
} else if accepts_json_or_all(req.headers()) {
|
||||||
Ok(plain_events_json(req, evq, ctx, pgqueue, ncc).await?)
|
Ok(plain_events_json(req, evq, ch_conf, ctx, ncc).await?)
|
||||||
} else {
|
} else {
|
||||||
let ret = response_err_msg(StatusCode::NOT_ACCEPTABLE, format!("unsupported accept {:?}", req))?;
|
let ret = response_err_msg(StatusCode::NOT_ACCEPTABLE, format!("unsupported accept {:?}", req))?;
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
@@ -102,13 +106,10 @@ async fn plain_events(
|
|||||||
async fn plain_events_cbor_framed(
|
async fn plain_events_cbor_framed(
|
||||||
req: Requ,
|
req: Requ,
|
||||||
evq: PlainEventsQuery,
|
evq: PlainEventsQuery,
|
||||||
|
ch_conf: ChannelTypeConfigGen,
|
||||||
ctx: &ReqCtx,
|
ctx: &ReqCtx,
|
||||||
pgqueue: &PgQueue,
|
|
||||||
ncc: &NodeConfigCached,
|
ncc: &NodeConfigCached,
|
||||||
) -> Result<StreamResponse, Error> {
|
) -> Result<StreamResponse, Error> {
|
||||||
let ch_conf = chconf_from_events_quorum(&evq, ctx, pgqueue, ncc)
|
|
||||||
.await?
|
|
||||||
.ok_or_else(|| Error::with_msg_no_trace("channel not found"))?;
|
|
||||||
debug!("plain_events_cbor_framed chconf_from_events_quorum: {ch_conf:?} {req:?}");
|
debug!("plain_events_cbor_framed chconf_from_events_quorum: {ch_conf:?} {req:?}");
|
||||||
let open_bytes = OpenBoxedBytesViaHttp::new(ncc.node_config.cluster.clone());
|
let open_bytes = OpenBoxedBytesViaHttp::new(ncc.node_config.cluster.clone());
|
||||||
let stream = streams::plaineventscbor::plain_events_cbor_stream(&evq, ch_conf, ctx, Box::pin(open_bytes)).await?;
|
let stream = streams::plaineventscbor::plain_events_cbor_stream(&evq, ch_conf, ctx, Box::pin(open_bytes)).await?;
|
||||||
@@ -130,13 +131,10 @@ async fn plain_events_cbor_framed(
|
|||||||
async fn plain_events_json_framed(
|
async fn plain_events_json_framed(
|
||||||
req: Requ,
|
req: Requ,
|
||||||
evq: PlainEventsQuery,
|
evq: PlainEventsQuery,
|
||||||
|
ch_conf: ChannelTypeConfigGen,
|
||||||
ctx: &ReqCtx,
|
ctx: &ReqCtx,
|
||||||
pgqueue: &PgQueue,
|
|
||||||
ncc: &NodeConfigCached,
|
ncc: &NodeConfigCached,
|
||||||
) -> Result<StreamResponse, Error> {
|
) -> Result<StreamResponse, Error> {
|
||||||
let ch_conf = chconf_from_events_quorum(&evq, ctx, pgqueue, ncc)
|
|
||||||
.await?
|
|
||||||
.ok_or_else(|| Error::with_msg_no_trace("channel not found"))?;
|
|
||||||
debug!("plain_events_json_framed chconf_from_events_quorum: {ch_conf:?} {req:?}");
|
debug!("plain_events_json_framed chconf_from_events_quorum: {ch_conf:?} {req:?}");
|
||||||
let open_bytes = OpenBoxedBytesViaHttp::new(ncc.node_config.cluster.clone());
|
let open_bytes = OpenBoxedBytesViaHttp::new(ncc.node_config.cluster.clone());
|
||||||
let stream = streams::plaineventsjson::plain_events_json_stream(&evq, ch_conf, ctx, Box::pin(open_bytes)).await?;
|
let stream = streams::plaineventsjson::plain_events_json_stream(&evq, ch_conf, ctx, Box::pin(open_bytes)).await?;
|
||||||
@@ -148,18 +146,14 @@ async fn plain_events_json_framed(
|
|||||||
async fn plain_events_json(
|
async fn plain_events_json(
|
||||||
req: Requ,
|
req: Requ,
|
||||||
evq: PlainEventsQuery,
|
evq: PlainEventsQuery,
|
||||||
|
ch_conf: ChannelTypeConfigGen,
|
||||||
ctx: &ReqCtx,
|
ctx: &ReqCtx,
|
||||||
pgqueue: &PgQueue,
|
|
||||||
ncc: &NodeConfigCached,
|
ncc: &NodeConfigCached,
|
||||||
) -> Result<StreamResponse, Error> {
|
) -> Result<StreamResponse, Error> {
|
||||||
let self_name = "plain_events_json";
|
let self_name = "plain_events_json";
|
||||||
debug!("{self_name} req: {:?}", req);
|
debug!("{self_name} req: {:?}", req);
|
||||||
let (_head, _body) = req.into_parts();
|
let (_head, _body) = req.into_parts();
|
||||||
// TODO handle None case better and return 404
|
// TODO handle None case better and return 404
|
||||||
let ch_conf = chconf_from_events_quorum(&evq, ctx, pgqueue, ncc)
|
|
||||||
.await
|
|
||||||
.map_err(Error::from)?
|
|
||||||
.ok_or_else(|| Error::with_msg_no_trace("channel not found"))?;
|
|
||||||
debug!("{self_name} chconf_from_events_quorum: {ch_conf:?}");
|
debug!("{self_name} chconf_from_events_quorum: {ch_conf:?}");
|
||||||
let open_bytes = OpenBoxedBytesViaHttp::new(ncc.node_config.cluster.clone());
|
let open_bytes = OpenBoxedBytesViaHttp::new(ncc.node_config.cluster.clone());
|
||||||
let item =
|
let item =
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ use nodenet::configquorum::find_config_basics_quorum;
|
|||||||
use query::api4::binned::BinnedQuery;
|
use query::api4::binned::BinnedQuery;
|
||||||
use query::api4::events::PlainEventsQuery;
|
use query::api4::events::PlainEventsQuery;
|
||||||
use scyllaconn::errconv::ErrConv;
|
use scyllaconn::errconv::ErrConv;
|
||||||
use scyllaconn::range::ScyllaSeriesRange;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
@@ -524,6 +523,8 @@ impl IocForChannel {
|
|||||||
&[&q.backend, &q.name],
|
&[&q.backend, &q.name],
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
drop(pg_client);
|
||||||
|
pgjh.await??;
|
||||||
if let Some(row) = rows.first() {
|
if let Some(row) = rows.first() {
|
||||||
let ioc_addr = row.get(0);
|
let ioc_addr = row.get(0);
|
||||||
let ret = IocForChannelRes { ioc_addr };
|
let ret = IocForChannelRes { ioc_addr };
|
||||||
@@ -626,7 +627,7 @@ impl ScyllaSeriesTsMsp {
|
|||||||
};
|
};
|
||||||
let chconf = shared_res
|
let chconf = shared_res
|
||||||
.pgqueue
|
.pgqueue
|
||||||
.chconf_best_matching_name_range_job(backend, name, nano_range)
|
.chconf_best_matching_name_range(backend, name, nano_range)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| Error::with_msg_no_trace(format!("error from pg worker: {e}")))?
|
.map_err(|e| Error::with_msg_no_trace(format!("error from pg worker: {e}")))?
|
||||||
.recv()
|
.recv()
|
||||||
@@ -734,6 +735,8 @@ impl AmbigiousChannelNames {
|
|||||||
&[],
|
&[],
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
drop(pg_client);
|
||||||
|
pgjh.await??;
|
||||||
let mut ret = AmbigiousChannelNamesResponse { ambigious: Vec::new() };
|
let mut ret = AmbigiousChannelNamesResponse { ambigious: Vec::new() };
|
||||||
for row in rows {
|
for row in rows {
|
||||||
let g = AmbigiousChannel {
|
let g = AmbigiousChannel {
|
||||||
@@ -748,16 +751,6 @@ impl AmbigiousChannelNames {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TestData01Iter {}
|
|
||||||
|
|
||||||
impl Iterator for TestData01Iter {
|
|
||||||
type Item = f64;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Msps(Vec<u64>);
|
struct Msps(Vec<u64>);
|
||||||
struct Lsps(Vec<u64>);
|
struct Lsps(Vec<u64>);
|
||||||
struct Pulses(Vec<u64>);
|
struct Pulses(Vec<u64>);
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ async fn scylla_chconf_from_sf_db_channel(
|
|||||||
} else {
|
} else {
|
||||||
// TODO let called function allow to return None instead of error-not-found
|
// TODO let called function allow to return None instead of error-not-found
|
||||||
let ret = pgqueue
|
let ret = pgqueue
|
||||||
.chconf_best_matching_name_range_job(channel.backend(), channel.name(), range)
|
.chconf_best_matching_name_range(channel.backend(), channel.name(), range)
|
||||||
.await?
|
.await?
|
||||||
.recv()
|
.recv()
|
||||||
.await??;
|
.await??;
|
||||||
|
|||||||
@@ -98,11 +98,11 @@ pub async fn find_config_basics_quorum(
|
|||||||
if let Some(_cfg) = &ncc.node.sf_databuffer {
|
if let Some(_cfg) = &ncc.node.sf_databuffer {
|
||||||
let channel = if channel.name().is_empty() {
|
let channel = if channel.name().is_empty() {
|
||||||
if let Some(_) = channel.series() {
|
if let Some(_) = channel.series() {
|
||||||
let (pgclient, _pgjh) = dbconn::create_connection(&ncc.node_config.cluster.database).await?;
|
pgqueue
|
||||||
let pgclient = std::sync::Arc::new(pgclient);
|
.find_sf_channel_by_series(channel)
|
||||||
dbconn::find_sf_channel_by_series(channel, pgclient)
|
|
||||||
.await
|
.await
|
||||||
.map_err(|e| Error::with_msg_no_trace(e.to_string()))?
|
.map_err(|e| Error::with_msg_no_trace(e.to_string()))?
|
||||||
|
.map_err(|e| Error::with_msg_no_trace(e.to_string()))?
|
||||||
} else {
|
} else {
|
||||||
channel
|
channel
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,12 +128,12 @@ pub async fn create_response_bytes_stream(
|
|||||||
scyqueue: Option<&ScyllaQueue>,
|
scyqueue: Option<&ScyllaQueue>,
|
||||||
ncc: &NodeConfigCached,
|
ncc: &NodeConfigCached,
|
||||||
) -> Result<BoxedBytesStream, Error> {
|
) -> Result<BoxedBytesStream, Error> {
|
||||||
info!(
|
debug!(
|
||||||
"create_response_bytes_stream {:?} {:?}",
|
"create_response_bytes_stream {:?} {:?} wasm1 {:?}",
|
||||||
evq.ch_conf().scalar_type(),
|
evq.ch_conf().scalar_type(),
|
||||||
evq.ch_conf().shape(),
|
evq.ch_conf().shape(),
|
||||||
|
evq.wasm1()
|
||||||
);
|
);
|
||||||
debug!("wasm1 {:?}", evq.wasm1());
|
|
||||||
let reqctx = netpod::ReqCtx::new_from_single_reqid(evq.reqid().into()).into();
|
let reqctx = netpod::ReqCtx::new_from_single_reqid(evq.reqid().into()).into();
|
||||||
if evq.create_errors_contains("nodenet_parse_query") {
|
if evq.create_errors_contains("nodenet_parse_query") {
|
||||||
let e = Error::DebugTest;
|
let e = Error::DebugTest;
|
||||||
|
|||||||
Reference in New Issue
Block a user