Redis config
This commit is contained in:
2
.github/workflows/general.yml
vendored
2
.github/workflows/general.yml
vendored
@@ -15,7 +15,7 @@ env:
|
|||||||
SQLX_FEATURES: "rustls,postgres"
|
SQLX_FEATURES: "rustls,postgres"
|
||||||
DATABASE_URL: postgres://postgres:password@postgres:5432/newsletter
|
DATABASE_URL: postgres://postgres:password@postgres:5432/newsletter
|
||||||
APP_DATABASE__HOST: postgres
|
APP_DATABASE__HOST: postgres
|
||||||
APP_REDIS_URI: redis://redis:6379
|
APP_KV_STORE__HOST: redis
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ application:
|
|||||||
port: 8080
|
port: 8080
|
||||||
host: "127.0.0.1"
|
host: "127.0.0.1"
|
||||||
base_url: "http://127.0.0.1:8080"
|
base_url: "http://127.0.0.1:8080"
|
||||||
|
email_client:
|
||||||
|
authorization_token: "secret-token"
|
||||||
database:
|
database:
|
||||||
host: "127.0.0.1"
|
host: "127.0.0.1"
|
||||||
port: 5432
|
port: 5432
|
||||||
@@ -10,6 +12,6 @@ database:
|
|||||||
password: "password"
|
password: "password"
|
||||||
require_ssl: false
|
require_ssl: false
|
||||||
timeout_milliseconds: 1000
|
timeout_milliseconds: 1000
|
||||||
email_client:
|
kv_store:
|
||||||
authorization_token: "secret-token"
|
host: "127.0.0.1"
|
||||||
redis_uri: "redis://127.0.0.1:6379"
|
port: 6379
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
use crate::domain::SubscriberEmail;
|
use crate::domain::SubscriberEmail;
|
||||||
|
use anyhow::Context;
|
||||||
use secrecy::{ExposeSecret, SecretString};
|
use secrecy::{ExposeSecret, SecretString};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_aux::field_attributes::deserialize_number_from_string;
|
use serde_aux::field_attributes::deserialize_number_from_string;
|
||||||
use sqlx::postgres::{PgConnectOptions, PgSslMode};
|
use sqlx::postgres::{PgConnectOptions, PgSslMode};
|
||||||
|
use tower_sessions_redis_store::{
|
||||||
|
RedisStore,
|
||||||
|
fred::prelude::{ClientLike, Pool},
|
||||||
|
};
|
||||||
|
|
||||||
pub fn get_configuration() -> Result<Settings, config::ConfigError> {
|
pub fn get_configuration() -> Result<Settings, config::ConfigError> {
|
||||||
let base_path = std::env::current_dir().expect("Failed to determine the current directory");
|
let base_path = std::env::current_dir().expect("Failed to determine the current directory");
|
||||||
@@ -60,7 +65,7 @@ pub struct Settings {
|
|||||||
pub application: ApplicationSettings,
|
pub application: ApplicationSettings,
|
||||||
pub database: DatabaseSettings,
|
pub database: DatabaseSettings,
|
||||||
pub email_client: EmailClientSettings,
|
pub email_client: EmailClientSettings,
|
||||||
pub redis_uri: SecretString,
|
pub kv_store: RedisSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize)]
|
#[derive(Clone, Deserialize)]
|
||||||
@@ -100,6 +105,35 @@ impl EmailClientSettings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize)]
|
||||||
|
pub struct RedisSettings {
|
||||||
|
pub host: String,
|
||||||
|
pub port: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RedisSettings {
|
||||||
|
pub fn connection_string(&self) -> String {
|
||||||
|
format!("redis://{}:{}", self.host, self.port)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn session_store(&self) -> Result<RedisStore<Pool>, anyhow::Error> {
|
||||||
|
let pool = Pool::new(
|
||||||
|
tower_sessions_redis_store::fred::prelude::Config::from_url(&self.connection_string())
|
||||||
|
.context("Failed to parse Redis URL string.")?,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
6,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
pool.connect();
|
||||||
|
pool.wait_for_connect()
|
||||||
|
.await
|
||||||
|
.context("Failed to connect to the Redis server.")?;
|
||||||
|
Ok(RedisStore::new(pool))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize)]
|
#[derive(Clone, Deserialize)]
|
||||||
pub struct DatabaseSettings {
|
pub struct DatabaseSettings {
|
||||||
pub username: String,
|
pub username: String,
|
||||||
|
|||||||
@@ -10,16 +10,12 @@ use axum::{
|
|||||||
routing::{delete, get, post},
|
routing::{delete, get, post},
|
||||||
};
|
};
|
||||||
use reqwest::{StatusCode, header};
|
use reqwest::{StatusCode, header};
|
||||||
use secrecy::ExposeSecret;
|
|
||||||
use sqlx::{PgPool, postgres::PgPoolOptions};
|
use sqlx::{PgPool, postgres::PgPoolOptions};
|
||||||
use std::{sync::Arc, time::Duration};
|
use std::{sync::Arc, time::Duration};
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
use tower_http::{services::ServeDir, trace::TraceLayer};
|
use tower_http::{services::ServeDir, trace::TraceLayer};
|
||||||
use tower_sessions::SessionManagerLayer;
|
use tower_sessions::SessionManagerLayer;
|
||||||
use tower_sessions_redis_store::{
|
use tower_sessions_redis_store::{RedisStore, fred::prelude::Pool};
|
||||||
RedisStore,
|
|
||||||
fred::prelude::{ClientLike, Config, Pool},
|
|
||||||
};
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -46,18 +42,11 @@ impl Application {
|
|||||||
))
|
))
|
||||||
.connect_lazy_with(configuration.database.with_db());
|
.connect_lazy_with(configuration.database.with_db());
|
||||||
let email_client = EmailClient::build(configuration.email_client).unwrap();
|
let email_client = EmailClient::build(configuration.email_client).unwrap();
|
||||||
let pool = Pool::new(
|
let redis_store = configuration
|
||||||
Config::from_url(configuration.redis_uri.expose_secret())
|
.kv_store
|
||||||
.expect("Failed to parse Redis URL string"),
|
.session_store()
|
||||||
None,
|
.await
|
||||||
None,
|
.context("Failed to acquire Redis session store.")?;
|
||||||
None,
|
|
||||||
6,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
pool.connect();
|
|
||||||
pool.wait_for_connect().await.unwrap();
|
|
||||||
let redis_store = RedisStore::new(pool);
|
|
||||||
let router = app(
|
let router = app(
|
||||||
connection_pool,
|
connection_pool,
|
||||||
email_client,
|
email_client,
|
||||||
|
|||||||
Reference in New Issue
Block a user