update to support user expire, timeout, and disconnect
This commit is contained in:
parent
fe65835f4a
commit
5fcd49e847
16 changed files with 744 additions and 238 deletions
|
|
@ -15,6 +15,7 @@ chattyness-admin-ui.workspace = true
|
|||
chattyness-user-ui.workspace = true
|
||||
chattyness-db.workspace = true
|
||||
chattyness-error.workspace = true
|
||||
chattyness-shared.workspace = true
|
||||
leptos.workspace = true
|
||||
leptos_meta.workspace = true
|
||||
leptos_router.workspace = true
|
||||
|
|
@ -57,6 +58,7 @@ ssr = [
|
|||
"chattyness-user-ui/ssr",
|
||||
"chattyness-db/ssr",
|
||||
"chattyness-error/ssr",
|
||||
"chattyness-shared/ssr",
|
||||
]
|
||||
# Unified hydrate feature - admin routes are lazy-loaded via #[lazy] macro
|
||||
hydrate = [
|
||||
|
|
|
|||
|
|
@ -14,12 +14,14 @@ mod server {
|
|||
use leptos_axum::{generate_route_list, LeptosRoutes};
|
||||
use sqlx::postgres::PgPoolOptions;
|
||||
use std::net::SocketAddr;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tower_http::services::ServeDir;
|
||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||
|
||||
use chattyness_app::{combined_shell, CombinedApp, CombinedAppState};
|
||||
use chattyness_shared::AppConfig;
|
||||
use chattyness_user_ui::api::WebSocketState;
|
||||
|
||||
/// CLI arguments.
|
||||
|
|
@ -42,6 +44,10 @@ mod server {
|
|||
/// Use secure cookies
|
||||
#[arg(long, env = "SECURE_COOKIES", default_value = "false")]
|
||||
secure_cookies: bool,
|
||||
|
||||
/// Path to TOML configuration file
|
||||
#[arg(long, short = 'c', env = "CONFIG_FILE")]
|
||||
config: Option<PathBuf>,
|
||||
}
|
||||
|
||||
pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
|
@ -60,6 +66,10 @@ mod server {
|
|||
// Parse arguments
|
||||
let args = Args::parse();
|
||||
|
||||
// Load configuration
|
||||
let config = AppConfig::load(args.config.as_deref())?;
|
||||
tracing::info!("Configuration loaded: {:?}", config);
|
||||
|
||||
tracing::info!("Starting Chattyness App Server");
|
||||
|
||||
// Create database pool for app access (fixed connection string, RLS-constrained)
|
||||
|
|
@ -74,6 +84,53 @@ mod server {
|
|||
|
||||
tracing::info!("Connected to database (app role with RLS)");
|
||||
|
||||
// Startup cleanup: clear all instance_members if configured
|
||||
// Uses SECURITY DEFINER function to bypass RLS
|
||||
if config.cleanup.clear_on_startup {
|
||||
tracing::info!("Clearing stale instance_members on startup...");
|
||||
let deleted: i64 = sqlx::query_scalar("SELECT scene.clear_all_instance_members()")
|
||||
.fetch_one(&pool)
|
||||
.await?;
|
||||
tracing::info!("Cleared {} stale instance_members", deleted);
|
||||
}
|
||||
|
||||
// Spawn background task for periodic stale member cleanup
|
||||
// Uses SECURITY DEFINER function to bypass RLS
|
||||
{
|
||||
let cleanup_pool = pool.clone();
|
||||
let cleanup_config = config.cleanup.clone();
|
||||
tokio::spawn(async move {
|
||||
let mut interval = tokio::time::interval(Duration::from_secs(
|
||||
cleanup_config.reap_interval_secs,
|
||||
));
|
||||
loop {
|
||||
interval.tick().await;
|
||||
let threshold = cleanup_config.stale_threshold_secs as f64;
|
||||
match sqlx::query_scalar::<_, i64>(
|
||||
"SELECT scene.clear_stale_instance_members($1)",
|
||||
)
|
||||
.bind(threshold)
|
||||
.fetch_one(&cleanup_pool)
|
||||
.await
|
||||
{
|
||||
Ok(deleted) => {
|
||||
if deleted > 0 {
|
||||
tracing::info!("Reaped {} stale instance_members", deleted);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Stale member cleanup failed: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
tracing::info!(
|
||||
"Started stale member reaper (interval: {}s, threshold: {}s)",
|
||||
config.cleanup.reap_interval_secs,
|
||||
config.cleanup.stale_threshold_secs
|
||||
);
|
||||
}
|
||||
|
||||
// Configure Leptos
|
||||
let cargo_toml = concat!(env!("CARGO_MANIFEST_DIR"), "/Cargo.toml");
|
||||
let conf = get_configuration(Some(cargo_toml)).unwrap();
|
||||
|
|
@ -118,6 +175,7 @@ mod server {
|
|||
pool: pool.clone(),
|
||||
leptos_options: leptos_options.clone(),
|
||||
ws_state: ws_state.clone(),
|
||||
ws_config: config.websocket.clone(),
|
||||
};
|
||||
let admin_api_state = chattyness_admin_ui::AdminAppState {
|
||||
pool: pool.clone(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue