Page MenuHomeDevCentral

D1863.id4705.diff
No OneTemporary

D1863.id4705.diff

diff --git a/Cargo.toml b/Cargo.toml
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,9 +19,15 @@
repository = "https://devcentral.nasqueron.org/source/limiting-factor/"
[dependencies]
-diesel = { version = "^1.0.0", features = ["postgres", "r2d2", "chrono"] }
+diesel = { version = "^1.0.0", features = ["postgres", "r2d2", "chrono"], optional = true }
dotenv = "0.9.0"
log = "^0.4.4"
-r2d2 = "^0.8.2"
+r2d2 = { version = "^0.8.2", optional = true }
rocket = "^0.3.16"
rocket_contrib = { version = "^0.3.16", features = [ "json" ] }
+
+[features]
+default = ["pgsql"]
+minimal = []
+
+pgsql = ["diesel", "r2d2"]
diff --git a/src/api/replies.rs b/src/api/replies.rs
--- a/src/api/replies.rs
+++ b/src/api/replies.rs
@@ -2,15 +2,15 @@
//!
//! This module provides useful traits and methods to craft API replies from an existing type.
-use std::error::Error;
-
-use diesel::result::DatabaseErrorInformation;
-use diesel::result::DatabaseErrorKind;
+#[cfg(feature = "pgsql")]
+use diesel::result::{DatabaseErrorInformation, DatabaseErrorKind, QueryResult};
+#[cfg(feature = "pgsql")]
use diesel::result::Error as ResultError;
-use diesel::result::QueryResult;
+
use rocket::http::Status;
use rocket::response::Failure;
use rocket_contrib::Json;
+use std::error::Error;
/* -------------------------------------------------------------
Custom types
@@ -30,6 +30,7 @@
fn into_json_response(self) -> ApiJsonResponse<T>;
}
+#[cfg(feature = "pgsql")]
impl<T> ApiResponse<T> for QueryResult<T> {
/// Prepares an API response from a query result.
///
@@ -92,6 +93,7 @@
fn into_failure_response(self) -> Failure;
}
+#[cfg(feature = "pgsql")]
impl FailureResponse for ResultError {
/// Consumes the error and creates a Failure 500 Internal server error response.
fn into_failure_response(self) -> Failure {
@@ -109,6 +111,7 @@
Failure::from(Status::InternalServerError)
}
+#[cfg(feature = "pgsql")]
fn build_database_error_response(error_kind: DatabaseErrorKind, info: Box<dyn DatabaseErrorInformation>) -> Failure {
match error_kind {
// Case IIIa - The query tries to do an INSERT violating an unique constraint
diff --git a/src/config.rs b/src/config.rs
--- a/src/config.rs
+++ b/src/config.rs
@@ -21,6 +21,7 @@
fn get_database_url(&self) -> &str;
fn get_entry_point(&self) -> &str;
fn get_database_pool_size(&self) -> u32;
+ fn with_database(&self) -> bool;
}
/* -------------------------------------------------------------
@@ -40,6 +41,7 @@
database_url: String,
entry_point: String,
database_pool_size: u32,
+ with_database: bool,
}
impl Config for DefaultConfig {
@@ -54,6 +56,8 @@
fn get_database_pool_size(&self) -> u32 {
self.database_pool_size
}
+
+ fn with_database(&self) -> bool { self.with_database }
}
impl DefaultConfig {
@@ -64,11 +68,17 @@
warn!(target: "config", "Can't parse .env: {}", error.description());
};
+ let with_database = env::var("LF_DISABLE_DATABASE").is_err();
+
let database_url = match env::var("DATABASE_URL") {
Ok(url) => url,
Err(e) => {
- error!(target: "config", "You need to specify a DATABASE_URL variable in the environment (or .env file).");
- return Err(Box::new(e));
+ if with_database {
+ error!(target: "config", "You need to specify a DATABASE_URL variable in the environment (or .env file).");
+ return Err(Box::new(e));
+ }
+
+ String::new()
}
};
@@ -92,7 +102,54 @@
database_url,
entry_point,
database_pool_size,
+ with_database,
})
}
}
+/* -------------------------------------------------------------
+ MinimalConfig
+
+ :: Config
+ :: sui generis implementation
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+/// This is a minimal implementation of the `Config` trait, which extracts the following variables
+/// from an .env file or environment:
+///
+/// - `API_ENTRY_POINT` (facultative, by default `/`): the mouting point of the API methods
+///
+/// It sets the server not to use a database.
+pub struct MinimalConfig {
+ entry_point: String,
+}
+
+impl Config for MinimalConfig {
+ fn get_database_url(&self) -> &str {
+ ""
+ }
+
+ fn get_entry_point(&self) -> &str {
+ &self.entry_point
+ }
+
+ fn get_database_pool_size(&self) -> u32 {
+ 0
+ }
+
+ fn with_database(&self) -> bool { false }
+}
+
+impl MinimalConfig {
+ pub fn parse_environment() -> ErrorResult<Self> {
+ if let Err(error) = dotenv() {
+ warn!(target: "config", "Can't parse .env: {}", error.description());
+ };
+
+ let entry_point = env::var("API_ENTRY_POINT").unwrap_or(String::from("/"));
+
+ Ok(MinimalConfig {
+ entry_point,
+ })
+ }
+}
diff --git a/src/kernel.rs b/src/kernel.rs
--- a/src/kernel.rs
+++ b/src/kernel.rs
@@ -4,6 +4,7 @@
use config::Config;
use config::DefaultConfig;
+use config::MinimalConfig;
use database::initialize_database_pool;
use database::test_database_connection;
use ErrorResult;
@@ -26,10 +27,15 @@
let config = self.get_config();
let routes = self.get_routes();
- ignite()
- .manage(
+ let mut server = ignite();
+
+ if config.with_database() {
+ server = server.manage(
initialize_database_pool(config.get_database_url(), config.get_database_pool_size())?
- )
+ );
+ }
+
+ server
.mount(config.get_entry_point(), routes.to_vec())
.launch();
@@ -42,8 +48,10 @@
// Initial connection to test if the database configuration works
{
let config = self.get_config();
- test_database_connection(config.get_database_url())?;
- info!(target: "runner", "Connection to database established.");
+ if config.with_database() {
+ test_database_connection(config.get_database_url())?;
+ info!(target: "runner", "Connection to database established.");
+ }
}
self.launch_server()?;
@@ -84,12 +92,16 @@
/// ```
///
/// The default configuration will be used and the server started.
-pub struct DefaultApplication {
- config: DefaultConfig,
+pub struct DefaultApplication<T>
+ where T: Config
+{
+ config: T,
routes: Box<Vec<Route>>,
}
-impl Application for DefaultApplication {
+impl<T> Application for DefaultApplication<T>
+ where T: Config
+{
fn get_config(&self) -> &dyn Config {
&self.config
}
@@ -99,15 +111,17 @@
}
}
-impl DefaultApplication {
- pub fn new (config: DefaultConfig, routes: Vec<Route>) -> Self {
+impl<T> DefaultApplication<T>
+ where T: Config
+{
+ pub fn new (config: T, routes: Vec<Route>) -> Self {
DefaultApplication {
config,
routes: Box::new(routes),
}
}
- /// Starts the application, prepares default configuration
+ /// Starts the application
///
/// # Exit codes
///
@@ -116,20 +130,52 @@
/// - 0: Graceful exit (currently not in use, as the application never stops)
/// - 1: Error during the application run (e.g. routes conflict or Rocket fairings issues)
/// - 2: Error parsing the configuration (e.g. no database URL has been defined)
- pub fn start_application (routes: Vec<Route>) {
+ pub fn start (&mut self) {
info!(target: "runner", "Server initialized.");
+ if let Err(error) = self.run() {
+ error!(target: "runner", "{}", error.description());
+ process::exit(1);
+ }
+
+ process::exit(0);
+ }
+
+ /// Prepares an application with the default application and starts it
+ pub fn start_application (routes: Vec<Route>) {
let config = DefaultConfig::parse_environment().unwrap_or_else(|_error| {
process::exit(2);
});
- let mut app = Self::new(config, routes);
+ let mut app = DefaultApplication::new(config, routes);
+ app.start();
+ }
+}
- if let Err(error) = app.run() {
- error!(target: "runner", "{}", error.description());
- process::exit(1);
+/* -------------------------------------------------------------
+ Minimal application
+
+ :: Application
+ :: sui generis implementation, wrapper for DefaultApplication
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+pub struct MinimalApplication {}
+
+impl MinimalApplication {
+ pub fn new (config: MinimalConfig, routes: Vec<Route>) -> DefaultApplication<MinimalConfig> {
+ DefaultApplication {
+ config,
+ routes: Box::new(routes),
}
+ }
- process::exit(0);
+ pub fn start_application (routes: Vec<Route>) {
+ let config = MinimalConfig::parse_environment().unwrap_or_else(|_error| {
+ process::exit(2);
+ });
+
+ let mut app = DefaultApplication::new(config, routes);
+ app.start();
}
}
+
diff --git a/src/lib.rs b/src/lib.rs
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -29,9 +29,12 @@
//! }
//! ```
+#[cfg(feature = "pgsql")]
extern crate diesel;
extern crate dotenv;
-#[macro_use] extern crate log;
+#[macro_use]
+extern crate log;
+#[cfg(feature = "pgsql")]
extern crate r2d2;
extern crate rocket;
extern crate rocket_contrib;
@@ -42,9 +45,15 @@
pub mod api;
pub mod config;
-pub mod database;
pub mod kernel;
+/* -------------------------------------------------------------
+ Optional public features modules offered by this crate
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+#[cfg(feature = "pgsql")]
+pub mod database;
+
/* -------------------------------------------------------------
Custom types
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

File Metadata

Mime Type
text/plain
Expires
Wed, Mar 5, 06:28 (3 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2461462
Default Alt Text
D1863.id4705.diff (9 KB)

Event Timeline