-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6440891
commit b311c5e
Showing
13 changed files
with
272 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ | |
*.rock | ||
*.nix | ||
|
||
proto/*.rs | ||
/proto/*.rs | ||
venv/ | ||
build/ | ||
*.charm | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,47 +1,41 @@ | ||
use crate::{app::AppContext, features::common::entities::Vote}; | ||
use sqlx::Row; | ||
use crate::{app::AppContext, features::common::entities::VoteSummary}; | ||
use tracing::error; | ||
|
||
use super::errors::AppError; | ||
|
||
pub(crate) async fn get_votes_by_snap_id( | ||
app_ctx: &AppContext, | ||
snap_id: &str, | ||
) -> Result<Vec<Vote>, AppError> { | ||
let mut pool = app_ctx | ||
) -> Result<VoteSummary, AppError> { | ||
let mut pool = app_ctx | ||
.infrastructure() | ||
.repository() | ||
.await | ||
.map_err(|error| { | ||
error!("{error:?}"); | ||
AppError::FailedToGetRating | ||
})?; | ||
let result = sqlx::query( | ||
|
||
let result = sqlx::query_as::<_, VoteSummary>( // Changed to query_as with VoteSummary | ||
r#" | ||
SELECT | ||
votes.id, | ||
votes.snap_id, | ||
votes.vote_up | ||
FROM | ||
votes | ||
WHERE | ||
votes.snap_id = $1 | ||
"#, | ||
SELECT | ||
$1 as snap_id, // Explicitly select snap_id since it's not part of the GROUP BY | ||
COUNT(*) AS total_votes, | ||
COUNT(*) FILTER (WHERE votes.vote_up) AS positive_votes | ||
FROM | ||
votes | ||
WHERE | ||
votes.snap_id = $1 | ||
GROUP BY votes.snap_id | ||
"#, | ||
) | ||
.bind(snap_id) | ||
.fetch_all(&mut *pool) | ||
.fetch_one(&mut *pool) // Changed to fetch_one since we're expecting a single summarized row | ||
.await | ||
.map_err(|error| { | ||
error!("{error:?}"); | ||
AppError::Unknown | ||
})?; | ||
|
||
let votes: Vec<Vote> = result | ||
.into_iter() | ||
.map(|row| Vote { | ||
vote_up: row.get("vote_up"), | ||
}) | ||
.collect(); | ||
|
||
Ok(votes) | ||
Ok(result) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
use sqlx::FromRow; | ||
|
||
use crate::features::common::entities::{calculate_band, Rating, VoteSummary}; | ||
use crate::features::pb::chart as pb; | ||
|
||
pub type ClientHash = String; | ||
|
||
pub struct Chart { | ||
pub timeframe: pb::Timeframe, | ||
pub chart_data: Vec<ChartData>, | ||
} | ||
|
||
impl Chart { | ||
pub fn new(timeframe: pb::Timeframe, data: Vec<VoteSummary>) -> Self { | ||
let mut chart_data: Vec<ChartData> = data | ||
.into_iter() | ||
.map(|vote_summary| ChartData::from_vote_summary(vote_summary)) | ||
.collect(); | ||
|
||
chart_data.sort_by(|a, b| { | ||
b.raw_rating | ||
.partial_cmp(&a.raw_rating) | ||
.unwrap_or(std::cmp::Ordering::Equal) | ||
}); | ||
|
||
Chart { | ||
timeframe, | ||
chart_data, | ||
} | ||
} | ||
} | ||
|
||
#[derive(Debug, Clone, FromRow)] | ||
pub struct ChartData { | ||
pub raw_rating: f32, | ||
pub rating: Rating, | ||
} | ||
|
||
impl ChartData { | ||
pub fn new(raw_rating: f32, rating: Rating) -> Self { | ||
ChartData { raw_rating, rating } | ||
} | ||
|
||
pub fn from_vote_summary(vote_summary: VoteSummary) -> Self { | ||
let (raw_rating, ratings_band) = calculate_band(&vote_summary); | ||
let rating = Rating { | ||
snap_id: vote_summary.snap_id, | ||
total_votes: vote_summary.total_votes as u64, | ||
ratings_band, | ||
}; | ||
let raw_rating = raw_rating.unwrap_or(0.0) as f32; | ||
Self { raw_rating, rating } | ||
} | ||
|
||
pub fn into_dto(self) -> pb::ChartData { | ||
pb::ChartData { | ||
raw_rating: self.raw_rating, | ||
rating: Some(self.rating.into_dto()), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
use thiserror::Error; | ||
|
||
#[derive(Error, Debug)] | ||
pub enum ChartError { | ||
#[error("failed to get chart for timeframe")] | ||
FailedToGetChart, | ||
#[error("unknown chart error")] | ||
Unknown, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
use crate::features::pb::chart::Timeframe; | ||
use crate::app::AppContext; | ||
use crate::features::common::entities::VoteSummary; | ||
use tracing::error; | ||
|
||
use super::errors::ChartError; | ||
|
||
pub(crate) async fn get_votes_summary_by_timeframe( | ||
app_ctx: &AppContext, | ||
timeframe: Timeframe, | ||
) -> Result<Vec<VoteSummary>, ChartError> { | ||
let mut pool = app_ctx | ||
.infrastructure() | ||
.repository() | ||
.await | ||
.map_err(|error| { | ||
error!("{error:?}"); | ||
ChartError::FailedToGetChart | ||
})?; | ||
|
||
// Generate WHERE clause based on timeframe | ||
let where_clause = match timeframe { | ||
Timeframe::Week => "WHERE votes.created >= NOW() - INTERVAL '1 week'", | ||
Timeframe::Month => "WHERE votes.created >= NOW() - INTERVAL '1 month'", | ||
Timeframe::Unspecified => "", // Adjust as needed for Unspecified case | ||
}; | ||
|
||
let query = format!( | ||
r#" | ||
SELECT | ||
votes.snap_id, | ||
COUNT(*) AS total_votes, | ||
COUNT(*) FILTER (WHERE votes.vote_up) AS positive_votes | ||
FROM | ||
votes | ||
{} | ||
GROUP BY votes.snap_id | ||
"#, | ||
where_clause | ||
); | ||
|
||
let result = sqlx::query_as::<_, VoteSummary>(&query) | ||
.fetch_all(&mut *pool) | ||
.await | ||
.map_err(|error| { | ||
error!("{error:?}"); | ||
ChartError::Unknown | ||
})?; | ||
|
||
Ok(result) | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
use crate::app::AppContext; | ||
|
||
use crate::features::pb::chart::{GetChartRequest, GetChartResponse, Timeframe}; | ||
use tonic::{Request, Response, Status}; | ||
|
||
use crate::features::pb::chart::chart_server::Chart; | ||
|
||
use super::{service::ChartService, use_cases}; | ||
|
||
#[tonic::async_trait] | ||
impl Chart for ChartService { | ||
#[tracing::instrument] | ||
async fn get_chart( | ||
&self, | ||
request: Request<GetChartRequest>, | ||
) -> Result<Response<GetChartResponse>, Status> { | ||
let app_ctx = request.extensions().get::<AppContext>().unwrap().clone(); | ||
|
||
let GetChartRequest { timeframe } = request.into_inner(); | ||
|
||
let timeframe = match timeframe { | ||
0 => Timeframe::Unspecified, | ||
1 => Timeframe::Week, | ||
2=> Timeframe::Month, | ||
_ => Timeframe::Unspecified | ||
}; | ||
|
||
let result = use_cases::get_chart(&app_ctx, timeframe).await; | ||
|
||
match result { | ||
Ok(rating) => { | ||
let payload = GetChartResponse { timeframe: timeframe.into(), ordered_chart_data: todo!() }; | ||
Ok(Response::new(payload)) | ||
} | ||
Err(_error) => Err(Status::unknown("Internal server error")), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
pub mod entities; | ||
mod errors; | ||
mod infrastructure; | ||
pub mod interface; | ||
pub mod service; | ||
mod use_cases; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
use crate::features::pb::chart::chart_server::ChartServer; | ||
|
||
#[derive(Debug, Default)] | ||
pub struct ChartService; | ||
|
||
pub fn build_service() -> ChartServer<ChartService> { | ||
let service = ChartService; | ||
ChartServer::new(service) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
use crate::app::AppContext; | ||
use crate::features::chart::entities::Chart; | ||
use tracing::error; | ||
use super::{errors::ChartError, infrastructure::get_votes_summary_by_timeframe}; | ||
use crate::features::pb::chart::Timeframe; | ||
// use super::{entities::Rating, errors::AppError, infrastructure::get_votes_by_snap_id}; | ||
|
||
pub async fn get_chart(app_ctx: &AppContext, timeframe: Timeframe) -> Result<Chart, ChartError> { | ||
let votes = get_votes_summary_by_timeframe(app_ctx, timeframe) | ||
.await | ||
.map_err(|error| { | ||
error!("{error:?}"); | ||
ChartError::Unknown | ||
})?; | ||
|
||
let chart = Chart::new(timeframe, votes); | ||
|
||
Ok(chart) | ||
} |
Oops, something went wrong.