Service for editing/creating recipe
[recipes.git] / backend / src / data / asynchronous.rs
1 //! Functions to be called from actix code. They are asynchonrous and won't block worker thread caller.
2
3 use std::fmt;
4
5 use actix_web::{error::BlockingError, web};
6 use chrono::{prelude::*, Duration};
7
8 use super::db::*;
9 use crate::model;
10
11 #[derive(Debug)]
12 pub enum DBAsyncError {
13 DBError(DBError),
14 ActixError(BlockingError),
15 Other(String),
16 }
17
18 impl fmt::Display for DBAsyncError {
19 fn fmt(&self, f: &mut fmt::Formatter) -> std::result::Result<(), fmt::Error> {
20 write!(f, "{:?}", self)
21 }
22 }
23
24 impl std::error::Error for DBAsyncError {}
25
26 impl From<DBError> for DBAsyncError {
27 fn from(error: DBError) -> Self {
28 DBAsyncError::DBError(error)
29 }
30 }
31
32 impl From<BlockingError> for DBAsyncError {
33 fn from(error: BlockingError) -> Self {
34 DBAsyncError::ActixError(error)
35 }
36 }
37
38 impl DBAsyncError {
39 fn from_dyn_error(error: Box<dyn std::error::Error>) -> Self {
40 DBAsyncError::Other(error.to_string())
41 }
42 }
43
44 fn combine_errors<T>(
45 error: std::result::Result<std::result::Result<T, DBAsyncError>, BlockingError>,
46 ) -> Result<T> {
47 error?
48 }
49
50 type Result<T> = std::result::Result<T, DBAsyncError>;
51
52 impl Connection {
53 pub async fn get_all_recipe_titles_async(&self) -> Result<Vec<(i64, String)>> {
54 let self_copy = self.clone();
55 web::block(move || self_copy.get_all_recipe_titles().unwrap_or_default())
56 .await
57 .map_err(DBAsyncError::from)
58 }
59
60 pub async fn get_recipe_async(&self, id: i64) -> Result<model::Recipe> {
61 let self_copy = self.clone();
62 combine_errors(
63 web::block(move || self_copy.get_recipe(id).map_err(DBAsyncError::from)).await,
64 )
65 }
66
67 pub async fn load_user_async(&self, user_id: i64) -> Result<model::User> {
68 let self_copy = self.clone();
69 combine_errors(
70 web::block(move || self_copy.load_user(user_id).map_err(DBAsyncError::from)).await,
71 )
72 }
73
74 pub async fn sign_up_async(&self, email: &str, password: &str) -> Result<SignUpResult> {
75 let self_copy = self.clone();
76 let email_copy = email.to_string();
77 let password_copy = password.to_string();
78 combine_errors(
79 web::block(move || {
80 self_copy
81 .sign_up(&email_copy, &password_copy)
82 .map_err(DBAsyncError::from)
83 })
84 .await,
85 )
86 }
87
88 pub async fn validation_async(
89 &self,
90 token: &str,
91 validation_time: Duration,
92 ip: &str,
93 user_agent: &str,
94 ) -> Result<ValidationResult> {
95 let self_copy = self.clone();
96 let token_copy = token.to_string();
97 let ip_copy = ip.to_string();
98 let user_agent_copy = user_agent.to_string();
99 combine_errors(
100 web::block(move || {
101 self_copy
102 .validation(&token_copy, validation_time, &ip_copy, &user_agent_copy)
103 .map_err(DBAsyncError::from)
104 })
105 .await,
106 )
107 }
108
109 pub async fn sign_in_async(
110 &self,
111 email: &str,
112 password: &str,
113 ip: &str,
114 user_agent: &str,
115 ) -> Result<SignInResult> {
116 let self_copy = self.clone();
117 let email_copy = email.to_string();
118 let password_copy = password.to_string();
119 let ip_copy = ip.to_string();
120 let user_agent_copy = user_agent.to_string();
121 combine_errors(
122 web::block(move || {
123 self_copy
124 .sign_in(&email_copy, &password_copy, &ip_copy, &user_agent_copy)
125 .map_err(DBAsyncError::from)
126 })
127 .await,
128 )
129 }
130
131 pub async fn authentication_async(
132 &self,
133 token: &str,
134 ip: &str,
135 user_agent: &str,
136 ) -> Result<AuthenticationResult> {
137 let self_copy = self.clone();
138 let token_copy = token.to_string();
139 let ip_copy = ip.to_string();
140 let user_agent_copy = user_agent.to_string();
141 combine_errors(
142 web::block(move || {
143 self_copy
144 .authentication(&token_copy, &ip_copy, &user_agent_copy)
145 .map_err(DBAsyncError::from)
146 })
147 .await,
148 )
149 }
150
151 pub async fn sign_out_async(&self, token: &str) -> Result<()> {
152 let self_copy = self.clone();
153 let token_copy = token.to_string();
154 combine_errors(
155 web::block(move || self_copy.sign_out(&token_copy).map_err(DBAsyncError::from)).await,
156 )
157 }
158
159 pub async fn create_recipe_async(&self, user_id: i64) -> Result<i64> {
160 let self_copy = self.clone();
161 combine_errors(
162 web::block(move || self_copy.create_recipe(user_id).map_err(DBAsyncError::from)).await,
163 )
164 }
165
166 pub async fn set_recipe_title_async(&self, recipe_id: i64, title: &str) -> Result<()> {
167 let self_copy = self.clone();
168 let title_copy = title.to_string();
169 combine_errors(
170 web::block(move || {
171 self_copy
172 .set_recipe_title(recipe_id, &title_copy)
173 .map_err(DBAsyncError::from)
174 })
175 .await,
176 )
177 }
178
179 pub async fn set_recipe_description_async(
180 &self,
181 recipe_id: i64,
182 description: &str,
183 ) -> Result<()> {
184 let self_copy = self.clone();
185 let description_copy = description.to_string();
186 combine_errors(
187 web::block(move || {
188 self_copy
189 .set_recipe_description(recipe_id, &description_copy)
190 .map_err(DBAsyncError::from)
191 })
192 .await,
193 )
194 }
195 }