Skip to content

Commit 2d7c714

Browse files
committed
sentry - db - list_channels & list_channels_total_pages
1 parent d446e59 commit 2d7c714

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed

sentry/src/db/channel.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,23 @@
11
use crate::db::DbPool;
22
use bb8::RunError;
3+
use bb8_postgres::tokio_postgres::types::{accepts, FromSql, ToSql, Type};
4+
use chrono::{DateTime, Utc};
35
use primitives::{Channel, ChannelId, ValidatorId};
6+
use std::error::Error;
47
use std::str::FromStr;
58

9+
struct TotalPages(pub u64);
10+
impl<'a> FromSql<'a> for TotalPages {
11+
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
12+
let str_slice = <&str as FromSql>::from_sql(ty, raw)?;
13+
14+
Ok(Self(u64::from_str(str_slice)?))
15+
}
16+
17+
// Use a varchar or text, since otherwise `int8` fails deserialization
18+
accepts!(VARCHAR, TEXT);
19+
}
20+
621
pub async fn get_channel_by_id(
722
pool: &DbPool,
823
id: &ChannelId,
@@ -67,3 +82,93 @@ pub async fn insert_channel(
6782
})
6883
.await
6984
}
85+
86+
pub async fn list_channels(
87+
pool: &DbPool,
88+
skip: u64,
89+
limit: u32,
90+
creator: &Option<String>,
91+
validator: &Option<ValidatorId>,
92+
valid_until_ge: &DateTime<Utc>,
93+
) -> Result<Vec<Channel>, RunError<bb8_postgres::tokio_postgres::Error>> {
94+
let validator = validator.as_ref().map(|validator_id| {
95+
serde_json::Value::from_str(&format!(r#"[{{"id": "{}"}}]"#, validator_id))
96+
.expect("Not a valid json")
97+
});
98+
let (where_clauses, params) =
99+
channel_list_query_params(creator, validator.as_ref(), valid_until_ge);
100+
101+
pool
102+
.run(move |connection| {
103+
async move {
104+
// To understand why we use Order by, see Postgres Documentation: https://www.postgresql.org/docs/8.1/queries-limit.html
105+
let statement = format!("SELECT id, creator, deposit_asset, deposit_amount, valid_until, spec FROM channels WHERE {} ORDER BY id DESC LIMIT {} OFFSET {}", where_clauses.join(" AND "), limit, skip);
106+
match connection.prepare(&statement).await {
107+
Ok(stmt) => {
108+
match connection.query(&stmt, params.as_slice()).await {
109+
Ok(rows) => {
110+
let channels = rows.iter().map(Channel::from).collect();
111+
112+
Ok((channels, connection))
113+
},
114+
Err(e) => Err((e, connection)),
115+
}
116+
},
117+
Err(e) => Err((e, connection)),
118+
}
119+
}
120+
})
121+
.await
122+
}
123+
124+
pub async fn list_channels_total_pages(
125+
pool: &DbPool,
126+
creator: &Option<String>,
127+
validator: &Option<ValidatorId>,
128+
valid_until_ge: &DateTime<Utc>,
129+
) -> Result<u64, RunError<bb8_postgres::tokio_postgres::Error>> {
130+
let validator = validator.as_ref().map(|validator_id| {
131+
serde_json::Value::from_str(&format!(r#"[{{"id": "{}"}}]"#, validator_id))
132+
.expect("Not a valid json")
133+
});
134+
let (where_clauses, params) =
135+
channel_list_query_params(creator, validator.as_ref(), valid_until_ge);
136+
137+
pool.run(move |connection| {
138+
async move {
139+
let statement = format!(
140+
"SELECT COUNT(id)::varchar FROM channels WHERE {}",
141+
where_clauses.join(" AND ")
142+
);
143+
match connection.prepare(&statement).await {
144+
Ok(stmt) => match connection.query_one(&stmt, params.as_slice()).await {
145+
Ok(row) => Ok((row.get::<_, TotalPages>(0).0, connection)),
146+
Err(e) => Err((e, connection)),
147+
},
148+
Err(e) => Err((e, connection)),
149+
}
150+
}
151+
})
152+
.await
153+
}
154+
155+
fn channel_list_query_params<'a>(
156+
creator: &'a Option<String>,
157+
validator: Option<&'a serde_json::Value>,
158+
valid_until_ge: &'a DateTime<Utc>,
159+
) -> (Vec<String>, Vec<&'a (dyn ToSql + Sync)>) {
160+
let mut where_clauses = vec!["valid_until >= $1".to_string()];
161+
let mut params: Vec<&(dyn ToSql + Sync)> = vec![valid_until_ge];
162+
163+
if let Some(creator) = creator {
164+
where_clauses.push(format!("creator = ${}", params.len() + 1));
165+
params.push(creator);
166+
}
167+
168+
if let Some(validator) = validator {
169+
where_clauses.push(format!("spec->'validators' @> ${}", params.len() + 1));
170+
params.push(validator);
171+
}
172+
173+
(where_clauses, params)
174+
}

0 commit comments

Comments
 (0)