Reduce pg conn create, move lookup into worker mod

This commit is contained in:
Dominik Werder
2024-07-24 14:00:28 +02:00
parent a4228d03a4
commit 3889d8bf37
7 changed files with 81 additions and 71 deletions

View File

@@ -204,38 +204,3 @@ pub enum FindChannelError {
MultipleFound,
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);
}
}

View File

@@ -10,6 +10,7 @@ use netpod::ChConf;
use netpod::ChannelSearchQuery;
use netpod::ChannelSearchResult;
use netpod::Database;
use netpod::SfDbChannel;
use taskrun::tokio;
use tokio::task::JoinHandle;
use tokio_postgres::Client;
@@ -44,6 +45,10 @@ enum Job {
Sender<Result<Vec<Option<crate::channelinfo::ChannelInfo>>, crate::channelinfo::Error>>,
),
SearchChannel(ChannelSearchQuery, Sender<Result<ChannelSearchResult, err::Error>>),
SfChannelBySeries(
netpod::SfDbChannel,
Sender<Result<netpod::SfDbChannel, crate::FindChannelError>>,
),
}
#[derive(Debug, Clone)]
@@ -63,7 +68,7 @@ impl PgQueue {
Ok(rx)
}
pub async fn chconf_best_matching_name_range_job(
pub async fn chconf_best_matching_name_range(
&self,
backend: &str,
name: &str,
@@ -95,6 +100,17 @@ impl PgQueue {
let ret = rx.recv().await?;
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)]
@@ -154,6 +170,12 @@ impl PgWorker {
// 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();
}
}
// 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);
}
}

View File

@@ -24,6 +24,7 @@ use httpclient::StreamResponse;
use httpclient::ToJsonBody;
use netpod::log::*;
use netpod::req_uri_to_url;
use netpod::ChannelTypeConfigGen;
use netpod::FromUrl;
use netpod::NodeConfigCached;
use netpod::ReqCtx;
@@ -87,12 +88,15 @@ async fn plain_events(
pgqueue: &PgQueue,
ncc: &NodeConfigCached,
) -> 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()) {
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()) {
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()) {
Ok(plain_events_json(req, evq, ctx, pgqueue, ncc).await?)
Ok(plain_events_json(req, evq, ch_conf, ctx, ncc).await?)
} else {
let ret = response_err_msg(StatusCode::NOT_ACCEPTABLE, format!("unsupported accept {:?}", req))?;
Ok(ret)
@@ -102,13 +106,10 @@ async fn plain_events(
async fn plain_events_cbor_framed(
req: Requ,
evq: PlainEventsQuery,
ch_conf: ChannelTypeConfigGen,
ctx: &ReqCtx,
pgqueue: &PgQueue,
ncc: &NodeConfigCached,
) -> 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:?}");
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?;
@@ -130,13 +131,10 @@ async fn plain_events_cbor_framed(
async fn plain_events_json_framed(
req: Requ,
evq: PlainEventsQuery,
ch_conf: ChannelTypeConfigGen,
ctx: &ReqCtx,
pgqueue: &PgQueue,
ncc: &NodeConfigCached,
) -> 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:?}");
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?;
@@ -148,18 +146,14 @@ async fn plain_events_json_framed(
async fn plain_events_json(
req: Requ,
evq: PlainEventsQuery,
ch_conf: ChannelTypeConfigGen,
ctx: &ReqCtx,
pgqueue: &PgQueue,
ncc: &NodeConfigCached,
) -> Result<StreamResponse, Error> {
let self_name = "plain_events_json";
debug!("{self_name} req: {:?}", req);
let (_head, _body) = req.into_parts();
// 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:?}");
let open_bytes = OpenBoxedBytesViaHttp::new(ncc.node_config.cluster.clone());
let item =

View File

@@ -36,7 +36,6 @@ use nodenet::configquorum::find_config_basics_quorum;
use query::api4::binned::BinnedQuery;
use query::api4::events::PlainEventsQuery;
use scyllaconn::errconv::ErrConv;
use scyllaconn::range::ScyllaSeriesRange;
use serde::Deserialize;
use serde::Serialize;
use std::collections::BTreeMap;
@@ -524,6 +523,8 @@ impl IocForChannel {
&[&q.backend, &q.name],
)
.await?;
drop(pg_client);
pgjh.await??;
if let Some(row) = rows.first() {
let ioc_addr = row.get(0);
let ret = IocForChannelRes { ioc_addr };
@@ -626,7 +627,7 @@ impl ScyllaSeriesTsMsp {
};
let chconf = shared_res
.pgqueue
.chconf_best_matching_name_range_job(backend, name, nano_range)
.chconf_best_matching_name_range(backend, name, nano_range)
.await
.map_err(|e| Error::with_msg_no_trace(format!("error from pg worker: {e}")))?
.recv()
@@ -734,6 +735,8 @@ impl AmbigiousChannelNames {
&[],
)
.await?;
drop(pg_client);
pgjh.await??;
let mut ret = AmbigiousChannelNamesResponse { ambigious: Vec::new() };
for row in rows {
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 Lsps(Vec<u64>);
struct Pulses(Vec<u64>);

View File

@@ -220,7 +220,7 @@ async fn scylla_chconf_from_sf_db_channel(
} else {
// TODO let called function allow to return None instead of error-not-found
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?
.recv()
.await??;

View File

@@ -98,11 +98,11 @@ pub async fn find_config_basics_quorum(
if let Some(_cfg) = &ncc.node.sf_databuffer {
let channel = if channel.name().is_empty() {
if let Some(_) = channel.series() {
let (pgclient, _pgjh) = dbconn::create_connection(&ncc.node_config.cluster.database).await?;
let pgclient = std::sync::Arc::new(pgclient);
dbconn::find_sf_channel_by_series(channel, pgclient)
pgqueue
.find_sf_channel_by_series(channel)
.await
.map_err(|e| Error::with_msg_no_trace(e.to_string()))?
.map_err(|e| Error::with_msg_no_trace(e.to_string()))?
} else {
channel
}

View File

@@ -128,12 +128,12 @@ pub async fn create_response_bytes_stream(
scyqueue: Option<&ScyllaQueue>,
ncc: &NodeConfigCached,
) -> Result<BoxedBytesStream, Error> {
info!(
"create_response_bytes_stream {:?} {:?}",
debug!(
"create_response_bytes_stream {:?} {:?} wasm1 {:?}",
evq.ch_conf().scalar_type(),
evq.ch_conf().shape(),
evq.wasm1()
);
debug!("wasm1 {:?}", evq.wasm1());
let reqctx = netpod::ReqCtx::new_from_single_reqid(evq.reqid().into()).into();
if evq.create_errors_contains("nodenet_parse_query") {
let e = Error::DebugTest;