Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cat-gateway): Catalyst singed Documents indexing POST endpoint #1576

Merged
merged 31 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
eeb8cec
update query limits
Mr-Leshiy Jan 21, 2025
76e0199
fix
Mr-Leshiy Jan 21, 2025
f07579b
wip
Mr-Leshiy Jan 21, 2025
1d1b19a
fix
Mr-Leshiy Jan 21, 2025
35038ff
update test
Mr-Leshiy Jan 21, 2025
8447382
fix
Mr-Leshiy Jan 21, 2025
fe5816c
wip
Mr-Leshiy Jan 21, 2025
85029a1
initial TryFrom<DocumentIndexQueryFilter> for DocsQueryFilter impl
Mr-Leshiy Jan 21, 2025
14aa6b3
fix spelling
Mr-Leshiy Jan 21, 2025
3e4e759
fix
Mr-Leshiy Jan 21, 2025
3abc944
wip
Mr-Leshiy Jan 21, 2025
10f1a6c
wip
Mr-Leshiy Jan 21, 2025
df2ec2c
fix
Mr-Leshiy Jan 21, 2025
e2459ef
add metadata field for query_filter
Mr-Leshiy Jan 21, 2025
e9da4d6
wip
Mr-Leshiy Jan 21, 2025
2186f8f
wip
Mr-Leshiy Jan 22, 2025
7f6f3c5
wip
Mr-Leshiy Jan 22, 2025
6de70c9
fix
Mr-Leshiy Jan 22, 2025
ee024c3
fix
Mr-Leshiy Jan 22, 2025
25b4f63
add TODO comments
Mr-Leshiy Jan 22, 2025
40593ed
Merge branch 'main' into feat/sign-doc-post
stevenj Jan 23, 2025
b49fbe8
fix typo
Mr-Leshiy Jan 23, 2025
dacba45
Merge branch 'main' into feat/sign-doc-post
Mr-Leshiy Jan 23, 2025
affc6b4
update with the latest cat-signed-doc crate
Mr-Leshiy Jan 23, 2025
04301e9
update hurl
Mr-Leshiy Jan 23, 2025
4d31b82
invalid redundant Errors doc section
Mr-Leshiy Jan 23, 2025
2ef95ae
Merge branch 'main' into feat/sign-doc-post
Mr-Leshiy Jan 23, 2025
d834466
Merge branch 'main' into feat/sign-doc-post
Mr-Leshiy Jan 23, 2025
00b3de1
Merge branch 'main' into feat/sign-doc-post
Mr-Leshiy Jan 24, 2025
0af27e5
Merge branch 'main' into feat/sign-doc-post
stevenj Jan 24, 2025
e680799
Merge branch 'main' into feat/sign-doc-post
Mr-Leshiy Jan 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions catalyst-gateway/bin/src/db/event/common/eq_or_ranged_uuid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//! `EqOrRangedUuid` query conditional stmt object.

/// Search either by a singe UUID, or a Range of UUIDs
#[derive(Clone, Debug, PartialEq)]
pub(crate) enum EqOrRangedUuid {
/// Search by the exact UUID
Eq(uuid::Uuid),
/// Search in this UUID's range
Range {
/// Minimum UUID to find (inclusive)
min: uuid::Uuid,
/// Maximum UUID to find (inclusive)
max: uuid::Uuid,
},
}

impl EqOrRangedUuid {
/// Return a sql conditional statement by the provided `table_field`
pub(crate) fn conditional_stmt(&self, table_field: &str) -> String {
match self {
Self::Eq(id) => format!("{table_field} = '{id}'"),
Self::Range { min, max } => {
format!("{table_field} >= '{min}' AND {table_field} <= '{max}'")
},
}
}
}
1 change: 1 addition & 0 deletions catalyst-gateway/bin/src/db/event/common/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//! Reusable common database objects

pub(crate) mod eq_or_ranged_uuid;
pub(crate) mod query_limits;
29 changes: 19 additions & 10 deletions catalyst-gateway/bin/src/db/event/common/query_limits.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
//! `QueryLimits` query argument object.

#![allow(dead_code)]

use std::fmt::Display;

use crate::service::common::types::generic::query::pagination::{Limit, Page};
Expand Down Expand Up @@ -33,27 +31,38 @@ impl Display for QueryLimits {

impl QueryLimits {
/// Create a `QueryLimits` object without the any limits.
#[allow(dead_code)]
pub(crate) const ALL: QueryLimits = Self(QueryLimitsInner::All);
/// Create a `QueryLimits` object with the limit equals to `1`.
#[allow(dead_code)]
pub(crate) const ONE: QueryLimits = Self(QueryLimitsInner::Limit(1));

/// Create a `QueryLimits` object from the service `Limit` and `Page` values.
///
/// # Errors
/// - Invalid `limit` value, must be more than `0`.
/// - Invalid arguments, `limit` must be provided when `page` is not None.
pub(crate) fn new(limit: Option<Limit>, page: Option<Page>) -> anyhow::Result<Self> {
pub(crate) fn new(limit: Option<Limit>, page: Option<Page>) -> Self {
Mr-Leshiy marked this conversation as resolved.
Show resolved Hide resolved
match (limit, page) {
(Some(limit), Some(page)) => {
Ok(Self(QueryLimitsInner::LimitAndOffset(
Self(QueryLimitsInner::LimitAndOffset(limit.into(), page.into()))
},
(Some(limit), None) => {
Self(QueryLimitsInner::LimitAndOffset(
limit.into(),
Page::default().into(),
))
},
(None, Some(page)) => {
Self(QueryLimitsInner::LimitAndOffset(
Limit::default().into(),
page.into(),
)))
))
},
(Some(limit), None) => Ok(Self(QueryLimitsInner::Limit(limit.into()))),
(None, None) => Ok(Self(QueryLimitsInner::All)),
(None, Some(_)) => {
anyhow::bail!("Invalid arguments, `limit` must be provided when `page` is not None")
(None, None) => {
Self(QueryLimitsInner::LimitAndOffset(
Limit::default().into(),
Page::default().into(),
))
},
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ impl FullSignedDoc {
self.body.authors()
}

/// Returns the document metadata.
#[allow(dead_code)]
pub(crate) fn metadata(&self) -> Option<&serde_json::Value> {
self.body.metadata()
}

/// Returns the `SignedDocBody`.
#[allow(dead_code)]
pub(crate) fn body(&self) -> &SignedDocBody {
Expand Down
99 changes: 79 additions & 20 deletions catalyst-gateway/bin/src/db/event/signed_docs/query_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,90 @@

use std::fmt::Display;

use crate::db::event::common::eq_or_ranged_uuid::EqOrRangedUuid;

/// A `select_signed_docs` query filtering argument.
#[allow(dead_code)]
pub(crate) enum DocsQueryFilter {
/// All entries
All,
/// Select docs with the specific `type` field
DocType(uuid::Uuid),
/// Select docs with the specific `id` field
DocId(uuid::Uuid),
/// Select docs with the specific `id` and `ver` field
DocVer(uuid::Uuid, uuid::Uuid),
/// Select docs with the specific `authors` field
Author(String),
/// If all fields would be `None` the query will search for all entries from the db.
#[derive(Clone, Debug)]
pub(crate) struct DocsQueryFilter {
/// `type` field
doc_type: Option<uuid::Uuid>,
/// `id` field
id: Option<EqOrRangedUuid>,
/// `ver` field
ver: Option<EqOrRangedUuid>,
/// `metadata` field
metadata: Option<serde_json::Value>,
}

impl Display for DocsQueryFilter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::All => write!(f, "TRUE"),
Self::DocType(doc_type) => write!(f, "signed_docs.type = '{doc_type}'"),
Self::DocId(id) => write!(f, "signed_docs.id = '{id}'"),
Self::DocVer(id, ver) => {
write!(f, "signed_docs.id = '{id}' AND signed_docs.ver = '{ver}'")
},
Self::Author(author) => write!(f, "signed_docs.authors @> '{{ \"{author}\" }}'"),
use std::fmt::Write;
let mut query = "TRUE".to_string();

if let Some(doc_type) = &self.doc_type {
write!(&mut query, " AND signed_docs.type = '{doc_type}'")?;
}

if let Some(id) = &self.id {
write!(&mut query, " AND {}", id.conditional_stmt("signed_docs.id"))?;
}
if let Some(ver) = &self.ver {
write!(
&mut query,
" AND {}",
ver.conditional_stmt("signed_docs.ver")
)?;
}
if let Some(metadata) = &self.metadata {
write!(&mut query, " AND signed_docs.metadata @> '{metadata}'",)?;
}

write!(f, "{query}")
}
}

impl DocsQueryFilter {
/// Creates an empty filter stmt, so the query will retrieve all entries from the db.
pub fn all() -> Self {
DocsQueryFilter {
doc_type: None,
id: None,
ver: None,
metadata: None,
}
}

/// Set the `type` field filter condition
pub fn with_type(self, doc_type: uuid::Uuid) -> Self {
DocsQueryFilter {
doc_type: Some(doc_type),
..self
}
}

/// Set the `type` field filter condition
Mr-Leshiy marked this conversation as resolved.
Show resolved Hide resolved
pub fn with_id(self, id: EqOrRangedUuid) -> Self {
DocsQueryFilter {
id: Some(id),
..self
}
}

/// Set the `ver` field filter condition
pub fn with_ver(self, ver: EqOrRangedUuid) -> Self {
DocsQueryFilter {
ver: Some(ver),
..self
}
}

/// Set the `metadata` field filter condition
#[allow(dead_code)]
pub fn with_metadata(self, metadata: serde_json::Value) -> Self {
DocsQueryFilter {
metadata: Some(metadata),
..self
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,21 @@ impl SignedDocBody {
&self.ver
}

/// Returns the document type.
pub(crate) fn doc_type(&self) -> &uuid::Uuid {
&self.doc_type
}

/// Returns the document authors.
pub(crate) fn authors(&self) -> &Vec<String> {
&self.authors
}

/// Returns the document metadata.
pub(crate) fn metadata(&self) -> Option<&serde_json::Value> {
self.metadata.as_ref()
}

/// Returns all signed document fields for the event db queries
pub(crate) fn postgres_db_fields(&self) -> [&(dyn tokio_postgres::types::ToSql + Sync); 5] {
[
Expand Down
Loading
Loading