Skip to content

Commit 3ddaca2

Browse files
committed
Add "CreateNewsInsightCase".
1 parent 073053f commit 3ddaca2

File tree

11 files changed

+147
-5
lines changed

11 files changed

+147
-5
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use std::sync::Arc;
2+
3+
use anyhow::Result;
4+
use async_trait::async_trait;
5+
6+
use crate::execution::ports::repository::InsertNewsInsightInput;
7+
8+
use super::{
9+
super::{ports::repository::Repository, workshop::Workshop},
10+
Case,
11+
};
12+
13+
pub(crate) struct CreateNewsInsightCaseInput {
14+
pub(crate) source_name: String,
15+
pub(crate) article_id: String,
16+
pub(crate) fields: String,
17+
}
18+
19+
struct CreateNewsInsightCase {
20+
repository: Arc<dyn Repository>,
21+
input: CreateNewsInsightCaseInput,
22+
}
23+
24+
impl Workshop {
25+
pub(crate) async fn execute_create_news_insight_case(&self, input: CreateNewsInsightCaseInput) -> Result<()> {
26+
let case = CreateNewsInsightCase {
27+
repository: Arc::clone(&self.repository),
28+
input,
29+
};
30+
self.run_case(case).await
31+
}
32+
}
33+
34+
#[async_trait]
35+
impl Case for CreateNewsInsightCase {
36+
type Output = ();
37+
38+
async fn execute(self) -> Result<Self::Output> {
39+
self.repository
40+
.insert_news_insight(InsertNewsInsightInput {
41+
source_name: self.input.source_name,
42+
article_id: self.input.article_id,
43+
fields: self.input.fields,
44+
})
45+
.await?;
46+
Ok(())
47+
}
48+
}

chloria-backend/chloria-api/src/execution/cases/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub(crate) mod authenticate;
2+
pub(crate) mod create_news_insight;
23
pub(crate) mod read_news;
34

45
use anyhow::Result;

chloria-backend/chloria-api/src/execution/ports/repository.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,16 @@ pub(crate) struct SelectNewsOutput {
1717
pub(crate) image_path: Option<String>,
1818
}
1919

20+
pub(crate) struct InsertNewsInsightInput {
21+
pub(crate) source_name: String,
22+
pub(crate) article_id: String,
23+
pub(crate) fields: String,
24+
}
25+
2026
#[async_trait]
2127
#[automock] // See: https://github.com/asomers/mockall/issues/189#issuecomment-689145249
2228
pub(crate) trait Repository: Send + Sync {
2329
async fn select_client_api_secret(&self, api_key_input: &str) -> Result<Option<String>>;
2430
async fn select_news(&self, input: SelectNewsInput) -> Result<Vec<SelectNewsOutput>>;
31+
async fn insert_news_insight(&self, input: InsertNewsInsightInput) -> Result<()>;
2532
}

chloria-backend/chloria-api/src/infrastructure/repository/postgresql.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ use diesel::{
88
};
99

1010
use crate::{
11-
execution::ports::repository::{Repository, SelectNewsInput, SelectNewsOutput},
11+
execution::ports::repository::{InsertNewsInsightInput, Repository, SelectNewsInput, SelectNewsOutput},
1212
schema::{
1313
client_credentials::dsl::*,
1414
news::{self, dsl::*},
15+
news_insights,
1516
},
1617
};
1718

@@ -28,6 +29,14 @@ impl PostgresqlClient {
2829
}
2930
}
3031

32+
#[derive(Insertable, AsChangeset)]
33+
#[diesel(table_name = news_insights)]
34+
struct InsertNewsInsightValue {
35+
id: i32,
36+
fields: String,
37+
updated_at: DateTime<Local>,
38+
}
39+
3140
#[async_trait]
3241
impl Repository for PostgresqlClient {
3342
async fn select_client_api_secret(&self, api_key_input: &str) -> Result<Option<String>> {
@@ -58,4 +67,23 @@ impl Repository for PostgresqlClient {
5867
}
5968
Ok(outputs)
6069
}
70+
71+
async fn insert_news_insight(&self, input: InsertNewsInsightInput) -> Result<()> {
72+
let news_id: i32 = news
73+
.filter(source_name.eq(input.source_name).and(article_id.eq(input.article_id)))
74+
.select(news::id)
75+
.first(&mut self.pool.get()?)?;
76+
let value = InsertNewsInsightValue {
77+
id: news_id,
78+
fields: input.fields,
79+
updated_at: Local::now(),
80+
};
81+
diesel::insert_into(news_insights::table)
82+
.values(&value)
83+
.on_conflict(news_insights::id)
84+
.do_update()
85+
.set(&value)
86+
.execute(&mut self.pool.get()?)?;
87+
Ok(())
88+
}
6189
}

chloria-backend/chloria-api/src/interface/adapters/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
pub(super) mod auth;
2-
pub(super) mod read_news;
2+
pub(super) mod news;
33

44
use serde::Serialize;
55
use serde_json::Value;

chloria-backend/chloria-api/src/interface/adapters/read_news.rs renamed to chloria-backend/chloria-api/src/interface/adapters/news.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use chrono::NaiveDate;
99
use serde::Deserialize;
1010

1111
use super::{super::state::RouterState, ErrorResponse};
12-
use crate::execution::cases::read_news::ReadNewsCaseInput;
12+
use crate::execution::cases::{create_news_insight::CreateNewsInsightCaseInput, read_news::ReadNewsCaseInput};
1313

1414
#[derive(Deserialize)]
1515
pub(in super::super) struct ReadNewsRequest {
@@ -34,3 +34,26 @@ pub(in super::super) async fn read_news(
3434
];
3535
Ok((headers, body))
3636
}
37+
38+
#[derive(Deserialize)]
39+
pub(in super::super) struct CreateNewsInsightRequest {
40+
source_name: String,
41+
article_id: String,
42+
fields: String,
43+
}
44+
45+
pub(in super::super) async fn create_news_insight(
46+
State(state): State<RouterState>,
47+
Json(request): Json<CreateNewsInsightRequest>,
48+
) -> Result<(), (StatusCode, Json<ErrorResponse>)> {
49+
state
50+
.workshop
51+
.execute_create_news_insight_case(CreateNewsInsightCaseInput {
52+
source_name: request.source_name,
53+
article_id: request.article_id,
54+
fields: request.fields,
55+
})
56+
.await
57+
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, Json(e.to_string().into())))?;
58+
Ok(())
59+
}

chloria-backend/chloria-api/src/interface/router.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use tower::ServiceBuilder;
99
use super::{
1010
adapters::{
1111
auth::{authenticate, authorize},
12-
read_news::read_news,
12+
news::{create_news_insight, read_news},
1313
},
1414
state::{RouterState, RouterStateJwt},
1515
};
@@ -34,6 +34,7 @@ pub(crate) fn new(config: RouterConfig, workshop: Workshop) -> Router {
3434
.with_state(state.clone());
3535
let authorized_router = Router::new()
3636
.route("/news", get(read_news))
37+
.route("/news_insight", post(create_news_insight))
3738
.route_layer(ServiceBuilder::new().layer(middleware::from_fn_with_state(state.clone(), authorize)))
3839
.with_state(state.clone());
3940
let router = Router::new().merge(public_router).merge(authorized_router);

chloria-backend/chloria-api/src/schema.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ diesel::table! {
3636
}
3737
}
3838

39+
diesel::table! {
40+
news_insights (id) {
41+
id -> Int4,
42+
fields -> Nullable<Text>,
43+
created_at -> Timestamptz,
44+
updated_at -> Timestamptz,
45+
}
46+
}
47+
3948
diesel::joinable!(client_credentials -> clients (id));
49+
diesel::joinable!(news_insights -> news (id));
4050

41-
diesel::allow_tables_to_appear_in_same_query!(client_credentials, clients, news,);
51+
diesel::allow_tables_to_appear_in_same_query!(client_credentials, clients, news, news_insights,);

chloria-backend/chloria-job/src/schema.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,16 @@ diesel::table! {
1515
updated_at -> Timestamptz,
1616
}
1717
}
18+
19+
diesel::table! {
20+
news_insights (id) {
21+
id -> Int4,
22+
fields -> Nullable<Text>,
23+
created_at -> Timestamptz,
24+
updated_at -> Timestamptz,
25+
}
26+
}
27+
28+
diesel::joinable!(news_insights -> news (id));
29+
30+
diesel::allow_tables_to_appear_in_same_query!(news, news_insights,);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-- This file should undo anything in `up.sql`
2+
3+
DROP TABLE news_insights;

0 commit comments

Comments
 (0)