refactor: remove session auth, add DbType enum, native async broker
- Remove `auth`, `sessions-db` features and all tower-sessions/tower-sessions-sqlx-store deps - Delete `src/session.rs` (InfraSessionStore) - `ServerConfig`: remove `session_secret` field and `attach_session_layer()` helper - `db.rs`: add explicit `DbType` enum to `DatabaseConfig`; `connect()` now matches on `db_type` instead of sniffing URL prefixes; remove `connect_sqlite()` standalone fn - `broker/mod.rs`: replace `#[async_trait]` with native async fn (Rust 2024 AFIT) - `broker/nats.rs`: remove `#[async_trait]` to match trait definition - `ai/embeddings.rs`: remove sync `generate_embedding()` (wasteful thread spawn); keep only `generate_embedding_async()` as the public API - Default features: `["logging", "db-sqlx", "auth", "http"]` → `["logging"]` - Bump version to 0.1.11 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
121
Cargo.lock
generated
121
Cargo.lock
generated
@@ -533,17 +533,6 @@ version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
||||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
version = "0.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747"
|
||||
dependencies = [
|
||||
"percent-encoding",
|
||||
"time",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.4"
|
||||
@@ -1775,7 +1764,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "k-core"
|
||||
version = "0.1.10"
|
||||
version = "0.1.11"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-nats",
|
||||
@@ -1789,12 +1778,9 @@ dependencies = [
|
||||
"serde",
|
||||
"sqlx",
|
||||
"thiserror 2.0.17",
|
||||
"time",
|
||||
"tokio",
|
||||
"tower 0.5.2",
|
||||
"tower-http",
|
||||
"tower-sessions",
|
||||
"tower-sessions-sqlx-store",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"uuid",
|
||||
@@ -1878,7 +1864,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
||||
dependencies = [
|
||||
"scopeguard",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2958,25 +2943,6 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rmp"
|
||||
version = "0.8.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ba8be72d372b2c9b35542551678538b562e7cf86c3315773cae48dfbfe7790c"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rmp-serde"
|
||||
version = "1.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72f81bee8c8ef9b577d1681a70ebbc962c232461e397b22c208c43c04b67a155"
|
||||
dependencies = [
|
||||
"rmp",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rsa"
|
||||
version = "0.9.9"
|
||||
@@ -3479,7 +3445,6 @@ dependencies = [
|
||||
"sha2",
|
||||
"smallvec 1.15.1",
|
||||
"thiserror 2.0.17",
|
||||
"time",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tracing",
|
||||
@@ -3564,7 +3529,6 @@ dependencies = [
|
||||
"sqlx-core",
|
||||
"stringprep",
|
||||
"thiserror 2.0.17",
|
||||
"time",
|
||||
"tracing",
|
||||
"uuid",
|
||||
"whoami",
|
||||
@@ -3604,7 +3568,6 @@ dependencies = [
|
||||
"sqlx-core",
|
||||
"stringprep",
|
||||
"thiserror 2.0.17",
|
||||
"time",
|
||||
"tracing",
|
||||
"uuid",
|
||||
"whoami",
|
||||
@@ -3631,7 +3594,6 @@ dependencies = [
|
||||
"serde_urlencoded",
|
||||
"sqlx-core",
|
||||
"thiserror 2.0.17",
|
||||
"time",
|
||||
"tracing",
|
||||
"url",
|
||||
"uuid",
|
||||
@@ -4063,22 +4025,6 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-cookies"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "151b5a3e3c45df17466454bb74e9ecedecc955269bdedbf4d150dfa393b55a36"
|
||||
dependencies = [
|
||||
"axum-core 0.5.6",
|
||||
"cookie",
|
||||
"futures-util",
|
||||
"http",
|
||||
"parking_lot",
|
||||
"pin-project-lite",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-http"
|
||||
version = "0.6.8"
|
||||
@@ -4110,71 +4056,6 @@ version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
|
||||
|
||||
[[package]]
|
||||
name = "tower-sessions"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43a05911f23e8fae446005fe9b7b97e66d95b6db589dc1c4d59f6a2d4d4927d3"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"http",
|
||||
"time",
|
||||
"tokio",
|
||||
"tower-cookies",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tower-sessions-core",
|
||||
"tower-sessions-memory-store",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-sessions-core"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce8cce604865576b7751b7a6bc3058f754569a60d689328bb74c52b1d87e355b"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum-core 0.5.6",
|
||||
"base64 0.22.1",
|
||||
"futures",
|
||||
"http",
|
||||
"parking_lot",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror 2.0.17",
|
||||
"time",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-sessions-memory-store"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb05909f2e1420135a831dd5df9f5596d69196d0a64c3499ca474c4bd3d33242"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"time",
|
||||
"tokio",
|
||||
"tower-sessions-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-sessions-sqlx-store"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e054622079f57fc1a7d6a6089c9334f963d62028fe21dc9eddd58af9a78480b3"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"rmp-serde",
|
||||
"sqlx",
|
||||
"thiserror 1.0.69",
|
||||
"time",
|
||||
"tower-sessions-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.44"
|
||||
|
||||
23
Cargo.toml
23
Cargo.toml
@@ -1,20 +1,18 @@
|
||||
[package]
|
||||
name = "k-core"
|
||||
version = "0.1.10"
|
||||
version = "0.1.11"
|
||||
edition = "2024"
|
||||
|
||||
[features]
|
||||
default = ["logging", "db-sqlx", "auth", "http"]
|
||||
default = ["logging"]
|
||||
logging = ["dep:tracing", "dep:tracing-subscriber"]
|
||||
db-sqlx = ["dep:sqlx"]
|
||||
postgres = ["db-sqlx", "sqlx/postgres", "tower-sessions-sqlx-store?/postgres"]
|
||||
sqlite = ["db-sqlx", "sqlx/sqlite", "tower-sessions-sqlx-store?/sqlite"]
|
||||
auth = ["dep:tower-sessions"]
|
||||
sessions-db = ["auth", "dep:tower-sessions-sqlx-store"]
|
||||
postgres = ["db-sqlx", "sqlx/postgres"]
|
||||
sqlite = ["db-sqlx", "sqlx/sqlite"]
|
||||
ai = ["dep:fastembed", "dep:qdrant-client"]
|
||||
broker = []
|
||||
broker-nats = ["broker", "dep:async-nats", "dep:futures-util", "dep:futures-core"]
|
||||
http = ["dep:axum", "dep:tower", "dep:tower-http", "dep:time", "logging"]
|
||||
http = ["dep:axum", "dep:tower", "dep:tower-http", "logging"]
|
||||
|
||||
[dependencies]
|
||||
# Error handling
|
||||
@@ -22,7 +20,7 @@ thiserror = "2.0.17"
|
||||
anyhow = "1.0.100"
|
||||
|
||||
# Async
|
||||
tokio = { version = "1.48.0", features = ["full"]}
|
||||
tokio = { version = "1.48.0", features = ["full"] }
|
||||
|
||||
# Database
|
||||
sqlx = { version = "0.8.6", features = [
|
||||
@@ -39,10 +37,6 @@ tracing-subscriber = { version = "0.3.22", features = [
|
||||
"fmt",
|
||||
], optional = true }
|
||||
|
||||
# Auth
|
||||
tower-sessions = { version = "0.14.0", optional = true }
|
||||
tower-sessions-sqlx-store = { version = "0.15", optional = true}
|
||||
|
||||
# Utils
|
||||
chrono = { version = "0.4.42", features = ["serde"] }
|
||||
uuid = { version = "1.19.0", features = ["v4", "serde"] }
|
||||
@@ -59,8 +53,7 @@ async-nats = { version = "0.45", optional = true }
|
||||
# HTTP
|
||||
axum = { version = "0.8.8", features = ["macros"], optional = true }
|
||||
tower = { version = "0.5.2", optional = true }
|
||||
tower-http = { version = "0.6.2", features = ["cors", "trace"], optional = true}
|
||||
time = { version = "0.3", optional = true }
|
||||
tower-http = { version = "0.6.2", features = ["cors", "trace"], optional = true }
|
||||
|
||||
futures-util = { version = "0.3", optional = true }
|
||||
futures-core = {version = "0.3", optional = true }
|
||||
futures-core = { version = "0.3", optional = true }
|
||||
|
||||
@@ -20,33 +20,7 @@ impl FastEmbedAdapter {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn generate_embedding(&self, text: &str) -> anyhow::Result<Vec<f32>> {
|
||||
let model = self.model.clone();
|
||||
let text = text.to_string();
|
||||
|
||||
// FastEmbed is blocking, so we run it in a blocking task if we are in an async context,
|
||||
// but since this method signature doesn't force async, we wrap the internal logic.
|
||||
// For strictly async usage in k-core:
|
||||
let embeddings = std::thread::scope(|s| {
|
||||
s.spawn(|| {
|
||||
let mut model = model
|
||||
.lock()
|
||||
.map_err(|e| anyhow::anyhow!("Lock error: {}", e))?;
|
||||
model
|
||||
.embed(vec![text], None)
|
||||
.map_err(|e| anyhow::anyhow!("Embed error: {}", e))
|
||||
})
|
||||
.join()
|
||||
.map_err(|_| anyhow::anyhow!("Thread join error"))?
|
||||
})?;
|
||||
|
||||
embeddings
|
||||
.into_iter()
|
||||
.next()
|
||||
.ok_or_else(|| anyhow::anyhow!("No embedding generated"))
|
||||
}
|
||||
|
||||
/// Async wrapper for use in async contexts (like Axum handlers)
|
||||
/// Generate an embedding asynchronously using a blocking thread pool.
|
||||
pub async fn generate_embedding_async(&self, text: &str) -> anyhow::Result<Vec<f32>> {
|
||||
let model = self.model.clone();
|
||||
let text = text.to_string();
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
use async_trait::async_trait;
|
||||
use futures_core::Stream;
|
||||
use std::pin::Pin;
|
||||
|
||||
#[cfg(feature = "broker-nats")]
|
||||
pub mod nats;
|
||||
|
||||
#[async_trait]
|
||||
pub trait MessageBroker: Send + Sync {
|
||||
async fn publish(&self, topic: &str, payload: Vec<u8>) -> anyhow::Result<()>;
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use super::MessageBroker;
|
||||
use async_trait::async_trait;
|
||||
use futures_util::StreamExt;
|
||||
use std::pin::Pin;
|
||||
|
||||
@@ -15,7 +14,6 @@ impl NatsBroker {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl MessageBroker for NatsBroker {
|
||||
async fn publish(&self, topic: &str, payload: Vec<u8>) -> anyhow::Result<()> {
|
||||
self.client
|
||||
@@ -35,7 +33,6 @@ impl MessageBroker for NatsBroker {
|
||||
.await
|
||||
.map_err(|e| anyhow::anyhow!("NATS subscribe error: {}", e))?;
|
||||
|
||||
// Map NATS Message to generic Vec<u8>
|
||||
let stream = subscriber.map(|msg| msg.payload.to_vec());
|
||||
|
||||
Ok(Box::pin(stream))
|
||||
|
||||
76
src/db.rs
76
src/db.rs
@@ -8,9 +8,22 @@ use sqlx::Sqlite;
|
||||
#[cfg(feature = "postgres")]
|
||||
use sqlx::Postgres;
|
||||
|
||||
/// Explicitly declares which database engine to connect to.
|
||||
///
|
||||
/// Using an explicit type avoids URL-prefix sniffing in `connect()`.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||
pub enum DbType {
|
||||
#[default]
|
||||
#[cfg_attr(not(feature = "sqlite"), allow(dead_code))]
|
||||
Sqlite,
|
||||
#[cfg_attr(not(feature = "postgres"), allow(dead_code))]
|
||||
Postgres,
|
||||
}
|
||||
|
||||
/// Universal Database Configuration
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DatabaseConfig {
|
||||
pub db_type: DbType,
|
||||
pub url: String,
|
||||
pub max_connections: u32,
|
||||
pub min_connections: u32,
|
||||
@@ -22,6 +35,7 @@ impl Default for DatabaseConfig {
|
||||
#[cfg(feature = "sqlite")]
|
||||
{
|
||||
Self {
|
||||
db_type: DbType::Sqlite,
|
||||
url: "sqlite::memory:".to_string(),
|
||||
max_connections: 5,
|
||||
min_connections: 1,
|
||||
@@ -32,6 +46,7 @@ impl Default for DatabaseConfig {
|
||||
#[cfg(all(not(feature = "sqlite"), feature = "postgres"))]
|
||||
{
|
||||
Self {
|
||||
db_type: DbType::Postgres,
|
||||
url: "postgres://localhost:5432/mydb".to_string(),
|
||||
max_connections: 5,
|
||||
min_connections: 1,
|
||||
@@ -41,6 +56,7 @@ impl Default for DatabaseConfig {
|
||||
|
||||
#[cfg(not(any(feature = "sqlite", feature = "postgres")))]
|
||||
Self {
|
||||
db_type: DbType::Sqlite,
|
||||
url: "".to_string(),
|
||||
max_connections: 5,
|
||||
min_connections: 1,
|
||||
@@ -50,8 +66,9 @@ impl Default for DatabaseConfig {
|
||||
}
|
||||
|
||||
impl DatabaseConfig {
|
||||
pub fn new(url: impl Into<String>) -> Self {
|
||||
pub fn new(db_type: DbType, url: impl Into<String>) -> Self {
|
||||
Self {
|
||||
db_type,
|
||||
url: url.into(),
|
||||
..Default::default()
|
||||
}
|
||||
@@ -60,8 +77,9 @@ impl DatabaseConfig {
|
||||
#[cfg(feature = "sqlite")]
|
||||
pub fn in_memory() -> Self {
|
||||
Self {
|
||||
db_type: DbType::Sqlite,
|
||||
url: "sqlite::memory:".to_string(),
|
||||
max_connections: 1, // SQLite in-memory is single-connection
|
||||
max_connections: 1,
|
||||
min_connections: 1,
|
||||
..Default::default()
|
||||
}
|
||||
@@ -69,7 +87,6 @@ impl DatabaseConfig {
|
||||
}
|
||||
|
||||
/// A wrapper around various DB pools.
|
||||
/// The Template uses this type so it doesn't care if it's Sqlite or Postgres.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum DatabasePool {
|
||||
#[cfg(feature = "sqlite")]
|
||||
@@ -78,36 +95,33 @@ pub enum DatabasePool {
|
||||
Postgres(Pool<Postgres>),
|
||||
}
|
||||
|
||||
/// The single entry point for connecting to any DB.
|
||||
/// Connect to a database using the explicit `db_type` from `DatabaseConfig`.
|
||||
pub async fn connect(config: &DatabaseConfig) -> Result<DatabasePool, sqlx::Error> {
|
||||
// 1. Try Postgres if the feature is enabled AND the URL looks like postgres
|
||||
#[cfg(feature = "postgres")]
|
||||
if config.url.starts_with("postgres://") || config.url.starts_with("postgresql://") {
|
||||
let pool = sqlx::postgres::PgPoolOptions::new()
|
||||
.max_connections(config.max_connections)
|
||||
.acquire_timeout(config.acquire_timeout)
|
||||
.connect(&config.url)
|
||||
.await?;
|
||||
return Ok(DatabasePool::Postgres(pool));
|
||||
}
|
||||
match config.db_type {
|
||||
#[cfg(feature = "postgres")]
|
||||
DbType::Postgres => {
|
||||
let pool = sqlx::postgres::PgPoolOptions::new()
|
||||
.max_connections(config.max_connections)
|
||||
.acquire_timeout(config.acquire_timeout)
|
||||
.connect(&config.url)
|
||||
.await?;
|
||||
Ok(DatabasePool::Postgres(pool))
|
||||
}
|
||||
|
||||
// 2. Fallback to Sqlite if the feature is enabled
|
||||
#[cfg(feature = "sqlite")]
|
||||
{
|
||||
let pool = sqlx::sqlite::SqlitePoolOptions::new()
|
||||
.max_connections(config.max_connections)
|
||||
.acquire_timeout(config.acquire_timeout)
|
||||
.connect(&config.url)
|
||||
.await?;
|
||||
#[cfg(feature = "sqlite")]
|
||||
DbType::Sqlite => {
|
||||
let pool = sqlx::sqlite::SqlitePoolOptions::new()
|
||||
.max_connections(config.max_connections)
|
||||
.acquire_timeout(config.acquire_timeout)
|
||||
.connect(&config.url)
|
||||
.await?;
|
||||
Ok(DatabasePool::Sqlite(pool))
|
||||
}
|
||||
|
||||
Ok(DatabasePool::Sqlite(pool))
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "sqlite"))]
|
||||
{
|
||||
Err(sqlx::Error::Configuration(
|
||||
#[allow(unreachable_patterns)]
|
||||
_ => Err(sqlx::Error::Configuration(
|
||||
"No supported database features enabled".into(),
|
||||
))
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +144,3 @@ impl DatabasePool {
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "sqlite")]
|
||||
pub async fn connect_sqlite(url: &str) -> Result<Pool<Sqlite>, sqlx::Error> {
|
||||
sqlx::sqlite::SqlitePoolOptions::new().connect(url).await
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
use axum::Router;
|
||||
use tower_http::cors::CorsLayer;
|
||||
use tower_http::trace::TraceLayer;
|
||||
use tower_sessions::{Expiry, SessionManagerLayer, SessionStore};
|
||||
|
||||
pub struct ServerConfig {
|
||||
pub cors_origins: Vec<String>,
|
||||
pub session_secret: Option<String>,
|
||||
}
|
||||
|
||||
pub fn apply_standard_middleware(app: Router, config: &ServerConfig) -> Router {
|
||||
@@ -24,7 +22,6 @@ pub fn apply_standard_middleware(app: Router, config: &ServerConfig) -> Router {
|
||||
])
|
||||
.allow_credentials(true);
|
||||
|
||||
// Configure CORS origins
|
||||
let mut allowed_origins = Vec::new();
|
||||
for origin in &config.cors_origins {
|
||||
if let Ok(value) = origin.parse::<axum::http::HeaderValue>() {
|
||||
@@ -38,15 +35,3 @@ pub fn apply_standard_middleware(app: Router, config: &ServerConfig) -> Router {
|
||||
|
||||
app.layer(cors).layer(TraceLayer::new_for_http())
|
||||
}
|
||||
|
||||
/// Helper to attach a session layer with standard K-Suite configuration
|
||||
pub fn attach_session_layer<S>(app: Router, store: S) -> Router
|
||||
where
|
||||
S: SessionStore + Clone + Send + Sync + 'static,
|
||||
{
|
||||
let session_layer = SessionManagerLayer::new(store)
|
||||
.with_secure(false) // Set to true if you handle HTTPS termination in the app
|
||||
.with_expiry(Expiry::OnInactivity(time::Duration::days(7)));
|
||||
|
||||
app.layer(session_layer)
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@ pub mod ai;
|
||||
|
||||
#[cfg(feature = "broker")]
|
||||
pub mod broker;
|
||||
#[cfg(feature = "auth")]
|
||||
pub mod session;
|
||||
|
||||
#[cfg(feature = "http")]
|
||||
pub mod http;
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
// Only compile this module if we have the store dependency AND sqlx enabled
|
||||
#[cfg(all(feature = "sessions-db", feature = "db-sqlx"))]
|
||||
pub mod store {
|
||||
use async_trait::async_trait;
|
||||
use tower_sessions::{
|
||||
SessionStore,
|
||||
session::{Id, Record},
|
||||
session_store,
|
||||
};
|
||||
|
||||
// We only import what is actually enabled by features
|
||||
#[cfg(feature = "postgres")]
|
||||
use tower_sessions_sqlx_store::PostgresStore;
|
||||
#[cfg(feature = "sqlite")]
|
||||
use tower_sessions_sqlx_store::SqliteStore;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum InfraSessionStore {
|
||||
#[cfg(feature = "sqlite")]
|
||||
Sqlite(SqliteStore),
|
||||
#[cfg(feature = "postgres")]
|
||||
Postgres(PostgresStore),
|
||||
// Fallback variant to allow compilation if sessions-db is enabled but no generic DB feature is selected
|
||||
// (Though in practice you should ensure your config validates this)
|
||||
#[allow(dead_code)]
|
||||
Unused,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl SessionStore for InfraSessionStore {
|
||||
async fn save(&self, session_record: &Record) -> session_store::Result<()> {
|
||||
match self {
|
||||
#[cfg(feature = "sqlite")]
|
||||
Self::Sqlite(store) => store.save(session_record).await,
|
||||
#[cfg(feature = "postgres")]
|
||||
Self::Postgres(store) => store.save(session_record).await,
|
||||
_ => Err(session_store::Error::Backend(
|
||||
"No database feature enabled".to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
async fn load(&self, session_id: &Id) -> session_store::Result<Option<Record>> {
|
||||
match self {
|
||||
#[cfg(feature = "sqlite")]
|
||||
Self::Sqlite(store) => store.load(session_id).await,
|
||||
#[cfg(feature = "postgres")]
|
||||
Self::Postgres(store) => store.load(session_id).await,
|
||||
_ => Err(session_store::Error::Backend(
|
||||
"No database feature enabled".to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
async fn delete(&self, session_id: &Id) -> session_store::Result<()> {
|
||||
match self {
|
||||
#[cfg(feature = "sqlite")]
|
||||
Self::Sqlite(store) => store.delete(session_id).await,
|
||||
#[cfg(feature = "postgres")]
|
||||
Self::Postgres(store) => store.delete(session_id).await,
|
||||
_ => Err(session_store::Error::Backend(
|
||||
"No database feature enabled".to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InfraSessionStore {
|
||||
pub async fn migrate(&self) -> anyhow::Result<()> {
|
||||
match self {
|
||||
#[cfg(feature = "sqlite")]
|
||||
Self::Sqlite(store) => store.migrate().await.map_err(|e| anyhow::anyhow!(e)),
|
||||
#[cfg(feature = "postgres")]
|
||||
Self::Postgres(store) => store.migrate().await.map_err(|e| anyhow::anyhow!(e)),
|
||||
_ => Ok(()), // No migration needed for no-op
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user