Renamed service to api
This commit is contained in:
168
api/src/db/mod.rs
Normal file
168
api/src/db/mod.rs
Normal file
@@ -0,0 +1,168 @@
|
||||
use crate::error::{ApiError, ApiResult};
|
||||
use diesel::{r2d2::ConnectionManager, PgConnection};
|
||||
use redis::{Client as RedisClient, aio::MultiplexedConnection as RedisConnection};
|
||||
use s3::{
|
||||
Bucket, Region, creds::Credentials, BucketConfiguration, request::ResponseData,
|
||||
bucket_ops::CreateBucketResponse,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::diesel_migrations::MigrationHarness;
|
||||
use lazy_static::lazy_static;
|
||||
use log::{error, info, warn};
|
||||
use r2d2;
|
||||
use std::env;
|
||||
|
||||
pub mod schema;
|
||||
|
||||
type Pool = r2d2::Pool<ConnectionManager<PgConnection>>;
|
||||
pub type DbConnection = r2d2::PooledConnection<ConnectionManager<PgConnection>>;
|
||||
|
||||
pub const MIGRATIONS: diesel_migrations::EmbeddedMigrations = embed_migrations!();
|
||||
|
||||
lazy_static! {
|
||||
static ref POOL: Pool = {
|
||||
let username = env::var("DATABASE_USER").expect("Database username is not set");
|
||||
let password = env::var("DATABASE_PASSWORD").expect("Database password is not set");
|
||||
let host = env::var("DATABASE_HOST").unwrap_or("localhost".to_string());
|
||||
let name = env::var("DATABASE_NAME").expect("Database name is not set");
|
||||
let port = env::var("DATABASE_PORT").unwrap_or("5432".to_string());
|
||||
let url = format!(
|
||||
"postgres://{}:{}@{}:{}/{}",
|
||||
username, password, host, port, name
|
||||
);
|
||||
let manager = ConnectionManager::<PgConnection>::new(url);
|
||||
Pool::builder()
|
||||
.test_on_check_out(true)
|
||||
.build(manager)
|
||||
.expect("Failed to create db pool")
|
||||
};
|
||||
static ref REDIS: RedisClient = {
|
||||
let host = env::var("REDIS_HOST").unwrap_or("localhost".to_string());
|
||||
let port = env::var("REDIS_PORT").unwrap_or("6379".to_string());
|
||||
let url = format!("redis://{}:{}", host, port);
|
||||
RedisClient::open(url).expect("Failed to create redis client")
|
||||
};
|
||||
static ref BUCKET: Bucket = {
|
||||
let url = env::var("MINIO_HOST").unwrap_or("localhost".to_string());
|
||||
let port = env::var("MINIO_PORT").unwrap_or("9000".to_string());
|
||||
let user = env::var("MINIO_ROOT_USER").expect("MINIO_ROOT_USER is not set");
|
||||
let password = env::var("MINIO_ROOT_PASSWORD").expect("MINIO_ROOT_PASSWORD is not set");
|
||||
let base_url = format!("http://{}:{}", url, port);
|
||||
|
||||
let region = Region::Custom {
|
||||
region: "".to_string(),
|
||||
endpoint: base_url,
|
||||
};
|
||||
|
||||
let credentials = Credentials {
|
||||
access_key: Some(user),
|
||||
secret_key: Some(password),
|
||||
security_token: None,
|
||||
session_token: None,
|
||||
expiration: None,
|
||||
};
|
||||
|
||||
*Bucket::new("aviation", region.clone(), credentials.clone())
|
||||
.expect("Failed to create S3 Bucket")
|
||||
.with_path_style()
|
||||
};
|
||||
}
|
||||
|
||||
pub async fn init() {
|
||||
lazy_static::initialize(&POOL);
|
||||
lazy_static::initialize(&REDIS);
|
||||
lazy_static::initialize(&BUCKET);
|
||||
match create_bucket().await {
|
||||
Ok(_) => info!("Bucket initialized"),
|
||||
Err(err) => match err.status {
|
||||
409 => warn!("Bucket already exists"),
|
||||
_ => error!("Failed to initialize bucket; {}", err),
|
||||
},
|
||||
};
|
||||
let mut pool: DbConnection = connection().expect("Failed to get db connection");
|
||||
match pool.run_pending_migrations(MIGRATIONS) {
|
||||
Ok(_) => info!("Database initialized"),
|
||||
Err(err) => error!("Failed to initialize database; {}", err),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn connection() -> ApiResult<DbConnection> {
|
||||
POOL
|
||||
.get()
|
||||
.map_err(|e| ApiError::new(500, format!("Failed getting db connection: {}", e)))
|
||||
}
|
||||
|
||||
pub fn redis_connection() -> ApiResult<redis::Connection> {
|
||||
let conn = REDIS.get_connection()?;
|
||||
Ok(conn)
|
||||
}
|
||||
|
||||
pub async fn redis_async_connection() -> ApiResult<RedisConnection> {
|
||||
let conn = REDIS.get_multiplexed_async_connection().await?;
|
||||
Ok(conn)
|
||||
}
|
||||
|
||||
async fn create_bucket() -> ApiResult<CreateBucketResponse> {
|
||||
let url = env::var("MINIO_URL").unwrap_or("localhost".to_string());
|
||||
let port = env::var("MINIO_PORT").unwrap_or("9000".to_string());
|
||||
let user = env::var("MINIO_ROOT_USER").expect("MINIO_ROOT_USER is not set");
|
||||
let password = env::var("MINIO_ROOT_PASSWORD").expect("MINIO_ROOT_PASSWORD is not set");
|
||||
let base_url = format!("http://{}:{}", url, port);
|
||||
|
||||
let region = Region::Custom {
|
||||
region: "".to_string(),
|
||||
endpoint: base_url,
|
||||
};
|
||||
|
||||
let credentials = Credentials {
|
||||
access_key: Some(user),
|
||||
secret_key: Some(password),
|
||||
security_token: None,
|
||||
session_token: None,
|
||||
expiration: None,
|
||||
};
|
||||
let bucket_name = "aviation";
|
||||
let response = Bucket::create_with_path_style(
|
||||
bucket_name,
|
||||
region,
|
||||
credentials,
|
||||
BucketConfiguration::default(),
|
||||
)
|
||||
.await?;
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
pub async fn upload_file(path: &str, content: &[u8]) -> ApiResult<ResponseData> {
|
||||
let response = BUCKET.put_object(path, content).await?;
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
pub async fn get_file(path: &str) -> ApiResult<Vec<u8>> {
|
||||
let response = BUCKET.get_object(path).await?;
|
||||
let bytes = response.bytes();
|
||||
Ok(bytes.to_vec())
|
||||
}
|
||||
|
||||
pub async fn delete_file(path: &str) -> ApiResult<ResponseData> {
|
||||
let response = BUCKET.delete_object(path).await?;
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Response<T> {
|
||||
pub data: T,
|
||||
pub meta: Option<Metadata>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Metadata {
|
||||
pub page: i32,
|
||||
pub limit: i32,
|
||||
pub total: i64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
pub struct Coordinate {
|
||||
pub lon: f64,
|
||||
pub lat: f64,
|
||||
}
|
||||
41
api/src/db/schema.rs
Normal file
41
api/src/db/schema.rs
Normal file
@@ -0,0 +1,41 @@
|
||||
diesel::table! {
|
||||
use diesel::sql_types::*;
|
||||
use postgis_diesel::sql_types::*;
|
||||
airports (icao) {
|
||||
icao -> Text,
|
||||
category -> Text,
|
||||
name -> Text,
|
||||
elevation_ft -> Float,
|
||||
iso_country -> Text,
|
||||
iso_region -> Text,
|
||||
municipality -> Text,
|
||||
has_metar -> Bool,
|
||||
point -> Geometry,
|
||||
data -> Jsonb
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
metars (id) {
|
||||
id -> Integer,
|
||||
icao -> Text,
|
||||
observation_time -> Timestamp,
|
||||
raw_text -> Text,
|
||||
data -> Jsonb,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
users (email) {
|
||||
email -> Text,
|
||||
hash -> Text,
|
||||
role -> Text,
|
||||
first_name -> Text,
|
||||
last_name -> Text,
|
||||
updated_at -> Timestamp,
|
||||
created_at -> Timestamp,
|
||||
profile_picture -> Nullable<Text>,
|
||||
favorites -> Array<Text>,
|
||||
verified -> Bool,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user