application.rs 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. use crate::{
  2. config::{get_configuration, DatabaseSettings, Settings},
  3. context::AppContext,
  4. routers::*,
  5. ws_service::WSServer,
  6. };
  7. use actix::Actor;
  8. use actix_web::{dev::Server, middleware, web, web::Data, App, HttpServer, Scope};
  9. use sqlx::{postgres::PgPoolOptions, PgPool};
  10. use std::{net::TcpListener, sync::Arc};
  11. pub struct Application {
  12. port: u16,
  13. server: Server,
  14. }
  15. impl Application {
  16. pub async fn build(configuration: Settings) -> Result<Self, std::io::Error> {
  17. let address = format!(
  18. "{}:{}",
  19. configuration.application.host, configuration.application.port
  20. );
  21. let listener = TcpListener::bind(&address)?;
  22. let port = listener.local_addr().unwrap().port();
  23. let app_ctx = init_app_context(&configuration).await;
  24. let server = run(listener, app_ctx)?;
  25. Ok(Self { port, server })
  26. }
  27. pub async fn run_until_stopped(self) -> Result<(), std::io::Error> { self.server.await }
  28. }
  29. pub fn run(listener: TcpListener, app_ctx: AppContext) -> Result<Server, std::io::Error> {
  30. let AppContext { ws_server, pg_pool } = app_ctx;
  31. let ws_server = Data::new(ws_server);
  32. let pg_pool = Data::new(pg_pool);
  33. let server = HttpServer::new(move || {
  34. App::new()
  35. .wrap(middleware::Logger::default())
  36. .app_data(web::JsonConfig::default().limit(4096))
  37. .service(ws_scope())
  38. .service(user_scope())
  39. .app_data(ws_server.clone())
  40. .app_data(pg_pool.clone())
  41. })
  42. .listen(listener)?
  43. .run();
  44. Ok(server)
  45. }
  46. fn ws_scope() -> Scope { web::scope("/ws").service(ws::start_connection) }
  47. fn user_scope() -> Scope {
  48. web::scope("/user").service(web::resource("/register").route(web::post().to(user::register)))
  49. }
  50. async fn init_app_context(configuration: &Settings) -> AppContext {
  51. let _ = flowy_log::Builder::new("flowy").env_filter("Debug").build();
  52. let pg_pool = get_connection_pool(&configuration.database)
  53. .await
  54. .expect(&format!(
  55. "Failed to connect to Postgres at {:?}.",
  56. configuration.database
  57. ));
  58. let ws_server = WSServer::new().start();
  59. AppContext::new(ws_server, pg_pool)
  60. }
  61. pub async fn get_connection_pool(configuration: &DatabaseSettings) -> Result<PgPool, sqlx::Error> {
  62. PgPoolOptions::new()
  63. .connect_timeout(std::time::Duration::from_secs(5))
  64. .connect_with(configuration.with_db())
  65. .await
  66. }