use std::ops::Deref; use actix::prelude::{Actor, Handler, Message, SyncContext}; use actix_web::{error, Error}; use diesel::pg::PgConnection; use diesel::r2d2::{ConnectionManager, Pool, PoolError, PooledConnection}; use model::{NewTask, Task}; type PgPool = Pool>; type PgPooledConnection = PooledConnection>; pub fn init_pool(database_url: &str) -> Result { let manager = ConnectionManager::::new(database_url); Pool::builder().build(manager) } pub struct DbExecutor(pub PgPool); impl DbExecutor { pub fn get_conn(&self) -> Result { self.0.get().map_err(|e| error::ErrorInternalServerError(e)) } } impl Actor for DbExecutor { type Context = SyncContext; } pub struct AllTasks; impl Message for AllTasks { type Result = Result, Error>; } impl Handler for DbExecutor { type Result = Result, Error>; fn handle(&mut self, _: AllTasks, _: &mut Self::Context) -> Self::Result { Task::all(self.get_conn()?.deref()) .map_err(|_| error::ErrorInternalServerError("Error inserting task")) } } pub struct CreateTask { pub description: String, } impl Message for CreateTask { type Result = Result<(), Error>; } impl Handler for DbExecutor { type Result = Result<(), Error>; fn handle(&mut self, todo: CreateTask, _: &mut Self::Context) -> Self::Result { let new_task = NewTask { description: todo.description, }; Task::insert(new_task, self.get_conn()?.deref()) .map(|_| ()) .map_err(|_| error::ErrorInternalServerError("Error inserting task")) } } pub struct ToggleTask { pub id: i32, } impl Message for ToggleTask { type Result = Result<(), Error>; } impl Handler for DbExecutor { type Result = Result<(), Error>; fn handle(&mut self, task: ToggleTask, _: &mut Self::Context) -> Self::Result { Task::toggle_with_id(task.id, self.get_conn()?.deref()) .map(|_| ()) .map_err(|_| error::ErrorInternalServerError("Error inserting task")) } } pub struct DeleteTask { pub id: i32, } impl Message for DeleteTask { type Result = Result<(), Error>; } impl Handler for DbExecutor { type Result = Result<(), Error>; fn handle(&mut self, task: DeleteTask, _: &mut Self::Context) -> Self::Result { Task::delete_with_id(task.id, self.get_conn()?.deref()) .map(|_| ()) .map_err(|_| error::ErrorInternalServerError("Error inserting task")) } }