Extend binned line to requested end
This commit is contained in:
@@ -7,9 +7,8 @@ use crate::requests::accepts_octets;
|
||||
use crate::ServiceSharedResources;
|
||||
use daqbuf_err as err;
|
||||
use dbconn::worker::PgQueue;
|
||||
use err::thiserror;
|
||||
use err::ThisError;
|
||||
use http::header::CONTENT_TYPE;
|
||||
use http::request::Parts;
|
||||
use http::Method;
|
||||
use http::StatusCode;
|
||||
use httpclient::body_empty;
|
||||
@@ -24,6 +23,7 @@ use httpclient::ToJsonBody;
|
||||
use netpod::log::*;
|
||||
use netpod::req_uri_to_url;
|
||||
use netpod::timeunits::SEC;
|
||||
use netpod::ChannelTypeConfigGen;
|
||||
use netpod::FromUrl;
|
||||
use netpod::NodeConfigCached;
|
||||
use netpod::ReqCtx;
|
||||
@@ -40,25 +40,27 @@ use std::sync::Arc;
|
||||
use streams::collect::CollectResult;
|
||||
use streams::eventsplainreader::DummyCacheReadProvider;
|
||||
use streams::eventsplainreader::SfDatabufferEventReadProvider;
|
||||
use streams::streamtimeout::StreamTimeout2;
|
||||
use streams::timebin::cached::reader::EventsReadProvider;
|
||||
use streams::timebin::CacheReadProvider;
|
||||
use tracing::Instrument;
|
||||
use url::Url;
|
||||
use tracing::Span;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
#[cstm(name = "Api4Binned")]
|
||||
pub enum Error {
|
||||
ChannelNotFound,
|
||||
BadQuery(String),
|
||||
HttpLib(#[from] http::Error),
|
||||
ChannelConfig(crate::channelconfig::Error),
|
||||
Retrieval(#[from] crate::RetrievalError),
|
||||
EventsCbor(#[from] streams::plaineventscbor::Error),
|
||||
EventsJson(#[from] streams::plaineventsjson::Error),
|
||||
ServerError,
|
||||
BinnedStream(err::Error),
|
||||
TimebinnedJson(#[from] streams::timebinnedjson::Error),
|
||||
}
|
||||
autoerr::create_error_v1!(
|
||||
name(Error, "Api4Binned"),
|
||||
enum variants {
|
||||
ChannelNotFound,
|
||||
BadQuery(String),
|
||||
HttpLib(#[from] http::Error),
|
||||
ChannelConfig(crate::channelconfig::Error),
|
||||
Retrieval(#[from] crate::RetrievalError),
|
||||
EventsCbor(#[from] streams::plaineventscbor::Error),
|
||||
EventsJson(#[from] streams::plaineventsjson::Error),
|
||||
ServerError,
|
||||
BinnedStream(err::Error),
|
||||
TimebinnedJson(#[from] streams::timebinnedjson::Error),
|
||||
},
|
||||
);
|
||||
|
||||
impl From<crate::channelconfig::Error> for Error {
|
||||
fn from(value: crate::channelconfig::Error) -> Self {
|
||||
@@ -104,7 +106,7 @@ impl BinnedHandler {
|
||||
}
|
||||
_ => {
|
||||
error!("EventsHandler sees: {e}");
|
||||
Ok(error_response(e.public_message(), ctx.reqid()))
|
||||
Ok(error_response(e.to_string(), ctx.reqid()))
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -126,19 +128,61 @@ async fn binned(
|
||||
{
|
||||
Err(Error::ServerError)?;
|
||||
}
|
||||
if accepts_cbor_framed(req.headers()) {
|
||||
Ok(binned_cbor_framed(url, req, ctx, pgqueue, scyqueue, ncc).await?)
|
||||
} else if accepts_json_framed(req.headers()) {
|
||||
Ok(binned_json_framed(url, req, ctx, pgqueue, scyqueue, ncc).await?)
|
||||
} else if accepts_json_or_all(req.headers()) {
|
||||
Ok(binned_json_single(url, req, ctx, pgqueue, scyqueue, ncc).await?)
|
||||
} else if accepts_octets(req.headers()) {
|
||||
let reqid = ctx.reqid();
|
||||
let (head, _body) = req.into_parts();
|
||||
let query = BinnedQuery::from_url(&url).map_err(|e| {
|
||||
error!("binned_cbor_framed: {e:?}");
|
||||
Error::BadQuery(e.to_string())
|
||||
})?;
|
||||
let logspan = if query.log_level() == "trace" {
|
||||
trace!("enable trace for handler");
|
||||
tracing::span!(tracing::Level::INFO, "log_span_trace")
|
||||
} else if query.log_level() == "debug" {
|
||||
debug!("enable debug for handler");
|
||||
tracing::span!(tracing::Level::INFO, "log_span_debug")
|
||||
} else {
|
||||
tracing::Span::none()
|
||||
};
|
||||
let span1 = span!(
|
||||
Level::INFO,
|
||||
"httpret::binned_cbor_framed",
|
||||
reqid,
|
||||
beg = query.range().beg_u64() / SEC,
|
||||
end = query.range().end_u64() / SEC,
|
||||
ch = query.channel().name(),
|
||||
);
|
||||
span1.in_scope(|| {
|
||||
debug!("binned begin {:?}", query);
|
||||
});
|
||||
binned_instrumented(head, ctx, query, pgqueue, scyqueue, ncc, logspan.clone())
|
||||
.instrument(logspan)
|
||||
.instrument(span1)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn binned_instrumented(
|
||||
head: Parts,
|
||||
ctx: &ReqCtx,
|
||||
query: BinnedQuery,
|
||||
pgqueue: &PgQueue,
|
||||
scyqueue: Option<ScyllaQueue>,
|
||||
ncc: &NodeConfigCached,
|
||||
logspan: Span,
|
||||
) -> Result<StreamResponse, Error> {
|
||||
let res2 = HandleRes2::new(ctx, logspan, query.clone(), pgqueue, scyqueue, ncc).await?;
|
||||
if accepts_cbor_framed(&head.headers) {
|
||||
Ok(binned_cbor_framed(res2, ctx, ncc).await?)
|
||||
} else if accepts_json_framed(&head.headers) {
|
||||
Ok(binned_json_framed(res2, ctx, ncc).await?)
|
||||
} else if accepts_json_or_all(&head.headers) {
|
||||
Ok(binned_json_single(res2, ctx, ncc).await?)
|
||||
} else if accepts_octets(&head.headers) {
|
||||
Ok(error_response(
|
||||
format!("binary binned data not yet available"),
|
||||
ctx.reqid(),
|
||||
))
|
||||
} else {
|
||||
let ret = error_response(format!("Unsupported Accept: {:?}", req.headers()), ctx.reqid());
|
||||
let ret = error_response(format!("Unsupported Accept: {:?}", &head.headers), ctx.reqid());
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
@@ -182,48 +226,20 @@ fn make_read_provider(
|
||||
}
|
||||
|
||||
async fn binned_json_single(
|
||||
url: Url,
|
||||
req: Requ,
|
||||
res2: HandleRes2<'_>,
|
||||
ctx: &ReqCtx,
|
||||
pgqueue: &PgQueue,
|
||||
scyqueue: Option<ScyllaQueue>,
|
||||
ncc: &NodeConfigCached,
|
||||
_ncc: &NodeConfigCached,
|
||||
) -> Result<StreamResponse, Error> {
|
||||
// TODO unify with binned_json_framed
|
||||
debug!("binned_json_single {:?}", req);
|
||||
let reqid = crate::status_board().map_err(|_e| Error::ServerError)?.new_status_id();
|
||||
let (_head, _body) = req.into_parts();
|
||||
let query = BinnedQuery::from_url(&url).map_err(|e| {
|
||||
error!("binned_json: {e:?}");
|
||||
Error::BadQuery(e.to_string())
|
||||
})?;
|
||||
let ch_conf = ch_conf_from_binned(&query, ctx, pgqueue, ncc)
|
||||
.await?
|
||||
.ok_or_else(|| Error::ChannelNotFound)?;
|
||||
let span1 = span!(
|
||||
Level::INFO,
|
||||
"httpret::binned",
|
||||
reqid,
|
||||
beg = query.range().beg_u64() / SEC,
|
||||
end = query.range().end_u64() / SEC,
|
||||
ch = query.channel().name(),
|
||||
);
|
||||
span1.in_scope(|| {
|
||||
debug!("begin");
|
||||
});
|
||||
let open_bytes = Arc::pin(OpenBoxedBytesViaHttp::new(ncc.node_config.cluster.clone()));
|
||||
let (events_read_provider, cache_read_provider) =
|
||||
make_read_provider(ch_conf.name(), scyqueue, open_bytes, ctx, ncc);
|
||||
let timeout_provider = streamio::streamtimeout::StreamTimeout::boxed();
|
||||
debug!("binned_json_single");
|
||||
let item = streams::timebinnedjson::timebinned_json(
|
||||
query,
|
||||
ch_conf,
|
||||
res2.query,
|
||||
res2.ch_conf,
|
||||
ctx,
|
||||
cache_read_provider,
|
||||
events_read_provider,
|
||||
timeout_provider,
|
||||
res2.cache_read_provider,
|
||||
res2.events_read_provider,
|
||||
res2.timeout_provider,
|
||||
)
|
||||
.instrument(span1)
|
||||
.await?;
|
||||
match item {
|
||||
CollectResult::Some(item) => {
|
||||
@@ -245,50 +261,30 @@ async fn binned_json_single(
|
||||
}
|
||||
|
||||
async fn binned_json_framed(
|
||||
url: Url,
|
||||
req: Requ,
|
||||
res2: HandleRes2<'_>,
|
||||
ctx: &ReqCtx,
|
||||
pgqueue: &PgQueue,
|
||||
scyqueue: Option<ScyllaQueue>,
|
||||
ncc: &NodeConfigCached,
|
||||
) -> Result<StreamResponse, Error> {
|
||||
debug!("binned_json_framed {:?}", req);
|
||||
let reqid = crate::status_board().map_err(|_e| Error::ServerError)?.new_status_id();
|
||||
let (_head, _body) = req.into_parts();
|
||||
let query = BinnedQuery::from_url(&url).map_err(|e| {
|
||||
error!("binned_json_framed: {e:?}");
|
||||
Error::BadQuery(e.to_string())
|
||||
})?;
|
||||
debug!("binned_json_framed");
|
||||
// TODO handle None case better and return 404
|
||||
let ch_conf = ch_conf_from_binned(&query, ctx, pgqueue, ncc)
|
||||
let ch_conf = ch_conf_from_binned(&res2.query, ctx, res2.pgqueue, ncc)
|
||||
.await?
|
||||
.ok_or_else(|| Error::ChannelNotFound)?;
|
||||
let span1 = span!(
|
||||
Level::INFO,
|
||||
"httpret::binned",
|
||||
reqid,
|
||||
beg = query.range().beg_u64() / SEC,
|
||||
end = query.range().end_u64() / SEC,
|
||||
ch = query.channel().name(),
|
||||
);
|
||||
span1.in_scope(|| {
|
||||
debug!("begin");
|
||||
});
|
||||
let open_bytes = Arc::pin(OpenBoxedBytesViaHttp::new(ncc.node_config.cluster.clone()));
|
||||
let (events_read_provider, cache_read_provider) =
|
||||
make_read_provider(ch_conf.name(), scyqueue, open_bytes, ctx, ncc);
|
||||
make_read_provider(ch_conf.name(), res2.scyqueue, open_bytes, ctx, ncc);
|
||||
let timeout_provider = streamio::streamtimeout::StreamTimeout::boxed();
|
||||
let stream = streams::timebinnedjson::timebinned_json_framed(
|
||||
query,
|
||||
res2.query,
|
||||
ch_conf,
|
||||
ctx,
|
||||
cache_read_provider,
|
||||
events_read_provider,
|
||||
timeout_provider,
|
||||
)
|
||||
.instrument(span1)
|
||||
.await?;
|
||||
let stream = streams::lenframe::bytes_chunks_to_len_framed_str(stream);
|
||||
let stream = streams::instrument::InstrumentStream::new(stream, res2.logspan);
|
||||
let ret = response(StatusCode::OK)
|
||||
.header(CONTENT_TYPE, APP_JSON_FRAMED)
|
||||
.header(HEADER_NAME_REQUEST_ID, ctx.reqid())
|
||||
@@ -297,53 +293,74 @@ async fn binned_json_framed(
|
||||
}
|
||||
|
||||
async fn binned_cbor_framed(
|
||||
url: Url,
|
||||
req: Requ,
|
||||
res2: HandleRes2<'_>,
|
||||
ctx: &ReqCtx,
|
||||
pgqueue: &PgQueue,
|
||||
scyqueue: Option<ScyllaQueue>,
|
||||
ncc: &NodeConfigCached,
|
||||
) -> Result<StreamResponse, Error> {
|
||||
debug!("binned_cbor_framed {:?}", req);
|
||||
let reqid = crate::status_board().map_err(|_e| Error::ServerError)?.new_status_id();
|
||||
let (_head, _body) = req.into_parts();
|
||||
let query = BinnedQuery::from_url(&url).map_err(|e| {
|
||||
error!("binned_cbor_framed: {e:?}");
|
||||
Error::BadQuery(e.to_string())
|
||||
})?;
|
||||
debug!("binned_cbor_framed");
|
||||
// TODO handle None case better and return 404
|
||||
let ch_conf = ch_conf_from_binned(&query, ctx, pgqueue, ncc)
|
||||
let ch_conf = ch_conf_from_binned(&res2.query, ctx, res2.pgqueue, ncc)
|
||||
.await?
|
||||
.ok_or_else(|| Error::ChannelNotFound)?;
|
||||
let span1 = span!(
|
||||
Level::INFO,
|
||||
"httpret::binned_cbor_framed",
|
||||
reqid,
|
||||
beg = query.range().beg_u64() / SEC,
|
||||
end = query.range().end_u64() / SEC,
|
||||
ch = query.channel().name(),
|
||||
);
|
||||
span1.in_scope(|| {
|
||||
debug!("begin");
|
||||
});
|
||||
let open_bytes = Arc::pin(OpenBoxedBytesViaHttp::new(ncc.node_config.cluster.clone()));
|
||||
let (events_read_provider, cache_read_provider) =
|
||||
make_read_provider(ch_conf.name(), scyqueue, open_bytes, ctx, ncc);
|
||||
make_read_provider(ch_conf.name(), res2.scyqueue, open_bytes, ctx, ncc);
|
||||
let timeout_provider = streamio::streamtimeout::StreamTimeout::boxed();
|
||||
let stream = streams::timebinnedjson::timebinned_cbor_framed(
|
||||
query,
|
||||
res2.query,
|
||||
ch_conf,
|
||||
ctx,
|
||||
cache_read_provider,
|
||||
events_read_provider,
|
||||
timeout_provider,
|
||||
)
|
||||
.instrument(span1)
|
||||
.await?;
|
||||
let stream = streams::lenframe::bytes_chunks_to_framed(stream);
|
||||
let stream = streams::instrument::InstrumentStream::new(stream, res2.logspan);
|
||||
let ret = response(StatusCode::OK)
|
||||
.header(CONTENT_TYPE, APP_CBOR_FRAMED)
|
||||
.header(HEADER_NAME_REQUEST_ID, ctx.reqid())
|
||||
.body(body_stream(stream))?;
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
struct HandleRes2<'a> {
|
||||
logspan: Span,
|
||||
query: BinnedQuery,
|
||||
ch_conf: ChannelTypeConfigGen,
|
||||
events_read_provider: Arc<dyn EventsReadProvider>,
|
||||
cache_read_provider: Arc<dyn CacheReadProvider>,
|
||||
timeout_provider: Box<dyn StreamTimeout2>,
|
||||
pgqueue: &'a PgQueue,
|
||||
scyqueue: Option<ScyllaQueue>,
|
||||
}
|
||||
|
||||
impl<'a> HandleRes2<'a> {
|
||||
async fn new(
|
||||
ctx: &ReqCtx,
|
||||
logspan: Span,
|
||||
query: BinnedQuery,
|
||||
pgqueue: &'a PgQueue,
|
||||
scyqueue: Option<ScyllaQueue>,
|
||||
ncc: &NodeConfigCached,
|
||||
) -> Result<Self, Error> {
|
||||
let ch_conf = ch_conf_from_binned(&query, ctx, pgqueue, ncc)
|
||||
.await?
|
||||
.ok_or_else(|| Error::ChannelNotFound)?;
|
||||
let open_bytes = Arc::pin(OpenBoxedBytesViaHttp::new(ncc.node_config.cluster.clone()));
|
||||
let (events_read_provider, cache_read_provider) =
|
||||
make_read_provider(ch_conf.name(), scyqueue.clone(), open_bytes, ctx, ncc);
|
||||
let timeout_provider = streamio::streamtimeout::StreamTimeout::boxed();
|
||||
let ret = Self {
|
||||
logspan,
|
||||
query,
|
||||
ch_conf,
|
||||
events_read_provider,
|
||||
cache_read_provider,
|
||||
timeout_provider,
|
||||
pgqueue,
|
||||
scyqueue,
|
||||
};
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,7 +285,9 @@ async fn find_active(
|
||||
}
|
||||
}
|
||||
|
||||
#[pin_project::pin_project]
|
||||
struct FindActiveStream {
|
||||
#[pin]
|
||||
rx: Receiver<Result<ActiveChannelDesc, FindActiveError>>,
|
||||
}
|
||||
|
||||
@@ -308,9 +310,9 @@ impl FindActiveStream {
|
||||
impl Stream for FindActiveStream {
|
||||
type Item = Result<ActiveChannelDesc, FindActiveError>;
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
use Poll::*;
|
||||
match self.rx.poll_next_unpin(cx) {
|
||||
match self.project().rx.poll_next_unpin(cx) {
|
||||
Ready(Some(item)) => Ready(Some(item)),
|
||||
Ready(None) => Ready(None),
|
||||
Pending => Pending,
|
||||
|
||||
@@ -83,12 +83,12 @@ impl EventDataHandler {
|
||||
.await
|
||||
.map_err(|_| EventDataError::InternalError)?;
|
||||
let (evsubq,) = nodenet::conn::events_parse_input_query(frames).map_err(|_| EventDataError::QueryParse)?;
|
||||
info!("{:?}", evsubq);
|
||||
debug!("{:?}", evsubq);
|
||||
let logspan = if evsubq.log_level() == "trace" {
|
||||
trace!("enable trace for handler");
|
||||
trace!("emit trace span");
|
||||
tracing::span!(tracing::Level::INFO, "log_span_trace")
|
||||
} else if evsubq.log_level() == "debug" {
|
||||
debug!("enable debug for handler");
|
||||
debug!("emit debug span");
|
||||
tracing::span!(tracing::Level::INFO, "log_span_debug")
|
||||
} else {
|
||||
tracing::Span::none()
|
||||
|
||||
@@ -32,6 +32,7 @@ use netpod::APP_JSON_FRAMED;
|
||||
use netpod::HEADER_NAME_REQUEST_ID;
|
||||
use nodenet::client::OpenBoxedBytesViaHttp;
|
||||
use query::api4::events::PlainEventsQuery;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use streams::collect::CollectResult;
|
||||
use streams::instrument::InstrumentStream;
|
||||
@@ -39,7 +40,9 @@ use streams::lenframe::bytes_chunks_to_framed;
|
||||
use streams::lenframe::bytes_chunks_to_len_framed_str;
|
||||
use streams::plaineventscbor::plain_events_cbor_stream;
|
||||
use streams::plaineventsjson::plain_events_json_stream;
|
||||
use streams::streamtimeout::StreamTimeout2;
|
||||
use tracing::Instrument;
|
||||
use tracing::Span;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
#[cstm(name = "Api4Events")]
|
||||
@@ -134,7 +137,7 @@ impl EventsHandler {
|
||||
} else {
|
||||
tracing::Span::none()
|
||||
};
|
||||
match plain_events(req, evq, ctx, &shared_res.pgqueue, ncc)
|
||||
match plain_events_prep(req, evq, ctx, &shared_res.pgqueue, ncc, logspan.clone())
|
||||
.instrument(logspan)
|
||||
.await
|
||||
{
|
||||
@@ -144,100 +147,80 @@ impl EventsHandler {
|
||||
}
|
||||
}
|
||||
|
||||
async fn plain_events(
|
||||
async fn plain_events_prep(
|
||||
req: Requ,
|
||||
evq: PlainEventsQuery,
|
||||
ctx: &ReqCtx,
|
||||
pgqueue: &PgQueue,
|
||||
ncc: &NodeConfigCached,
|
||||
logspan: Span,
|
||||
) -> Result<StreamResponse, Error> {
|
||||
let ch_conf = chconf_from_events_quorum(&evq, ctx, pgqueue, ncc)
|
||||
.await?
|
||||
.ok_or_else(|| Error::ChannelNotFound)?;
|
||||
let res2 = HandleRes2::new(ctx, logspan, evq.clone(), pgqueue, ncc).await?;
|
||||
plain_events(res2, req).await
|
||||
}
|
||||
|
||||
async fn plain_events(res2: HandleRes2<'_>, req: Requ) -> Result<StreamResponse, Error> {
|
||||
if accepts_cbor_framed(req.headers()) {
|
||||
Ok(plain_events_cbor_framed(req, evq, ch_conf, ctx, ncc).await?)
|
||||
Ok(plain_events_cbor_framed(req, res2).await?)
|
||||
} else if accepts_json_framed(req.headers()) {
|
||||
Ok(plain_events_json_framed(req, evq, ch_conf, ctx, ncc).await?)
|
||||
Ok(plain_events_json_framed(req, res2).await?)
|
||||
} else if accepts_json_or_all(req.headers()) {
|
||||
Ok(plain_events_json(req, evq, ch_conf, ctx, ncc).await?)
|
||||
Ok(plain_events_json(req, res2).await?)
|
||||
} else {
|
||||
let ret = error_response(format!("unsupported accept"), ctx.reqid());
|
||||
let ret = error_response(format!("unsupported accept"), res2.ctx.reqid());
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
|
||||
async fn plain_events_cbor_framed(
|
||||
req: Requ,
|
||||
evq: PlainEventsQuery,
|
||||
ch_conf: ChannelTypeConfigGen,
|
||||
ctx: &ReqCtx,
|
||||
ncc: &NodeConfigCached,
|
||||
) -> Result<StreamResponse, Error> {
|
||||
debug!("plain_events_cbor_framed {ch_conf:?} {req:?}");
|
||||
let open_bytes = OpenBoxedBytesViaHttp::new(ncc.node_config.cluster.clone());
|
||||
let open_bytes = Arc::pin(open_bytes);
|
||||
let timeout_provider = streamio::streamtimeout::StreamTimeout::boxed();
|
||||
let stream = plain_events_cbor_stream(&evq, ch_conf, ctx, open_bytes, timeout_provider).await?;
|
||||
async fn plain_events_cbor_framed(req: Requ, res2: HandleRes2<'_>) -> Result<StreamResponse, Error> {
|
||||
debug!("plain_events_cbor_framed {:?} {:?}", res2.ch_conf, req);
|
||||
let stream = plain_events_cbor_stream(
|
||||
&res2.evq,
|
||||
res2.ch_conf,
|
||||
res2.ctx,
|
||||
res2.open_bytes,
|
||||
res2.timeout_provider,
|
||||
)
|
||||
.await?;
|
||||
let stream = bytes_chunks_to_framed(stream);
|
||||
let logspan = if evq.log_level() == "trace" {
|
||||
trace!("enable trace for handler");
|
||||
tracing::span!(tracing::Level::INFO, "log_span_trace")
|
||||
} else if evq.log_level() == "debug" {
|
||||
debug!("enable debug for handler");
|
||||
tracing::span!(tracing::Level::INFO, "log_span_debug")
|
||||
} else {
|
||||
tracing::Span::none()
|
||||
};
|
||||
let stream = InstrumentStream::new(stream, logspan);
|
||||
let stream = InstrumentStream::new(stream, res2.logspan);
|
||||
let ret = response(StatusCode::OK)
|
||||
.header(CONTENT_TYPE, APP_CBOR_FRAMED)
|
||||
.header(HEADER_NAME_REQUEST_ID, ctx.reqid())
|
||||
.header(HEADER_NAME_REQUEST_ID, res2.ctx.reqid())
|
||||
.body(body_stream(stream))?;
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
async fn plain_events_json_framed(
|
||||
req: Requ,
|
||||
evq: PlainEventsQuery,
|
||||
ch_conf: ChannelTypeConfigGen,
|
||||
ctx: &ReqCtx,
|
||||
ncc: &NodeConfigCached,
|
||||
) -> Result<StreamResponse, Error> {
|
||||
debug!("plain_events_json_framed {ch_conf:?} {req:?}");
|
||||
let open_bytes = OpenBoxedBytesViaHttp::new(ncc.node_config.cluster.clone());
|
||||
let open_bytes = Arc::pin(open_bytes);
|
||||
let timeout_provider = streamio::streamtimeout::StreamTimeout::boxed();
|
||||
let stream = plain_events_json_stream(&evq, ch_conf, ctx, open_bytes, timeout_provider).await?;
|
||||
async fn plain_events_json_framed(req: Requ, res2: HandleRes2<'_>) -> Result<StreamResponse, Error> {
|
||||
debug!("plain_events_json_framed {:?} {:?}", res2.ch_conf, req);
|
||||
let stream = plain_events_json_stream(
|
||||
&res2.evq,
|
||||
res2.ch_conf,
|
||||
res2.ctx,
|
||||
res2.open_bytes,
|
||||
res2.timeout_provider,
|
||||
)
|
||||
.await?;
|
||||
let stream = bytes_chunks_to_len_framed_str(stream);
|
||||
let stream = InstrumentStream::new(stream, res2.logspan);
|
||||
let ret = response(StatusCode::OK)
|
||||
.header(CONTENT_TYPE, APP_JSON_FRAMED)
|
||||
.header(HEADER_NAME_REQUEST_ID, ctx.reqid())
|
||||
.header(HEADER_NAME_REQUEST_ID, res2.ctx.reqid())
|
||||
.body(body_stream(stream))?;
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
async fn plain_events_json(
|
||||
req: Requ,
|
||||
evq: PlainEventsQuery,
|
||||
ch_conf: ChannelTypeConfigGen,
|
||||
ctx: &ReqCtx,
|
||||
ncc: &NodeConfigCached,
|
||||
) -> Result<StreamResponse, Error> {
|
||||
async fn plain_events_json(req: Requ, res2: HandleRes2<'_>) -> Result<StreamResponse, Error> {
|
||||
let self_name = "plain_events_json";
|
||||
debug!("{self_name} {ch_conf:?} {req:?}");
|
||||
debug!("{self_name} {:?} {:?}", res2.ch_conf, req);
|
||||
let (_head, _body) = req.into_parts();
|
||||
// TODO handle None case better and return 404
|
||||
debug!("{self_name} chconf_from_events_quorum: {ch_conf:?}");
|
||||
let open_bytes = OpenBoxedBytesViaHttp::new(ncc.node_config.cluster.clone());
|
||||
let open_bytes = Arc::pin(open_bytes);
|
||||
let timeout_provider = streamio::streamtimeout::StreamTimeout::boxed();
|
||||
let item = streams::plaineventsjson::plain_events_json(
|
||||
&evq,
|
||||
ch_conf,
|
||||
ctx,
|
||||
&ncc.node_config.cluster,
|
||||
open_bytes,
|
||||
timeout_provider,
|
||||
&res2.evq,
|
||||
res2.ch_conf,
|
||||
res2.ctx,
|
||||
&res2.ncc.node_config.cluster,
|
||||
res2.open_bytes,
|
||||
res2.timeout_provider,
|
||||
)
|
||||
.await;
|
||||
debug!("{self_name} returned {}", item.is_ok());
|
||||
@@ -252,7 +235,7 @@ async fn plain_events_json(
|
||||
CollectResult::Some(item) => {
|
||||
let ret = response(StatusCode::OK)
|
||||
.header(CONTENT_TYPE, APP_JSON)
|
||||
.header(HEADER_NAME_REQUEST_ID, ctx.reqid())
|
||||
.header(HEADER_NAME_REQUEST_ID, res2.ctx.reqid())
|
||||
.body(ToJsonBody::from(item.into_bytes()).into_body())?;
|
||||
debug!("{self_name} response created");
|
||||
Ok(ret)
|
||||
@@ -261,9 +244,48 @@ async fn plain_events_json(
|
||||
let ret = error_status_response(
|
||||
StatusCode::GATEWAY_TIMEOUT,
|
||||
format!("no data within timeout"),
|
||||
ctx.reqid(),
|
||||
res2.ctx.reqid(),
|
||||
);
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct HandleRes2<'a> {
|
||||
logspan: Span,
|
||||
evq: PlainEventsQuery,
|
||||
ch_conf: ChannelTypeConfigGen,
|
||||
open_bytes: Pin<Arc<OpenBoxedBytesViaHttp>>,
|
||||
timeout_provider: Box<dyn StreamTimeout2>,
|
||||
#[allow(unused)]
|
||||
pgqueue: &'a PgQueue,
|
||||
ctx: &'a ReqCtx,
|
||||
ncc: &'a NodeConfigCached,
|
||||
}
|
||||
|
||||
impl<'a> HandleRes2<'a> {
|
||||
async fn new(
|
||||
ctx: &'a ReqCtx,
|
||||
logspan: Span,
|
||||
evq: PlainEventsQuery,
|
||||
pgqueue: &'a PgQueue,
|
||||
ncc: &'a NodeConfigCached,
|
||||
) -> Result<Self, Error> {
|
||||
let ch_conf = chconf_from_events_quorum(&evq, ctx, pgqueue, ncc)
|
||||
.await?
|
||||
.ok_or_else(|| Error::ChannelNotFound)?;
|
||||
let open_bytes = Arc::pin(OpenBoxedBytesViaHttp::new(ncc.node_config.cluster.clone()));
|
||||
let timeout_provider = streamio::streamtimeout::StreamTimeout::boxed();
|
||||
let ret = Self {
|
||||
logspan,
|
||||
evq,
|
||||
ch_conf,
|
||||
open_bytes,
|
||||
timeout_provider,
|
||||
pgqueue,
|
||||
ctx,
|
||||
ncc,
|
||||
};
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ use netpod::ChannelSearchResult;
|
||||
use netpod::NodeConfigCached;
|
||||
use netpod::ACCEPT_ALL;
|
||||
use netpod::APP_JSON;
|
||||
use tracing::Instrument;
|
||||
|
||||
pub struct ChannelSearchHandler {}
|
||||
|
||||
@@ -55,7 +56,17 @@ impl ChannelSearchHandler {
|
||||
async fn channel_search(req: Requ, pgqueue: &PgQueue, ncc: &NodeConfigCached) -> Result<ChannelSearchResult, Error> {
|
||||
let url = req_uri_to_url(req.uri())?;
|
||||
let query = ChannelSearchQuery::from_url(&url)?;
|
||||
info!("search query: {:?}", query);
|
||||
let res = dbconn::search::search_channel(query, pgqueue, ncc).await?;
|
||||
let logspan = if query.log_level() == "trace" {
|
||||
trace!("enable trace for handler");
|
||||
tracing::span!(tracing::Level::INFO, "log_span_trace")
|
||||
} else if query.log_level() == "debug" {
|
||||
debug!("enable debug for handler");
|
||||
tracing::span!(tracing::Level::INFO, "log_span_debug")
|
||||
} else {
|
||||
tracing::Span::none()
|
||||
};
|
||||
let res = dbconn::search::search_channel(query, pgqueue, ncc)
|
||||
.instrument(logspan)
|
||||
.await?;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user