steg 2
This commit is contained in:
+60
-63
@@ -1,13 +1,19 @@
|
||||
use std::{sync::Arc, time::Instant};
|
||||
use std::time::Instant;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use redis::Client as RedisClient;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::PgPool;
|
||||
use tokio::sync::RwLock;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{config::AppConfig, error::AppError};
|
||||
pub use crate::events::{EventManifestSnapshot, EventSnapshot};
|
||||
pub use crate::sessions::{SessionSnapshot, SessionStartRequest};
|
||||
|
||||
use crate::{
|
||||
config::AppConfig,
|
||||
error::AppError,
|
||||
events::{EventsStore},
|
||||
sessions::{SessionDefaults, SessionsStore},
|
||||
users::{UserCreateRequest, UsersStore},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AppState {
|
||||
@@ -15,32 +21,9 @@ pub struct AppState {
|
||||
pub started_at: Instant,
|
||||
pub database_pool: Option<PgPool>,
|
||||
pub redis_client: Option<RedisClient>,
|
||||
current_user_id: Uuid,
|
||||
session: Arc<RwLock<Option<SessionSnapshot>>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
pub struct SessionStartRequest {
|
||||
pub locale_code: Option<String>,
|
||||
pub device_platform: Option<String>,
|
||||
pub device_model: Option<String>,
|
||||
pub os_version: Option<String>,
|
||||
pub app_version: Option<String>,
|
||||
pub experiment_variant: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct SessionSnapshot {
|
||||
pub session_id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
pub started_at: DateTime<Utc>,
|
||||
pub ended_at: Option<DateTime<Utc>>,
|
||||
pub experiment_variant: String,
|
||||
pub app_version: String,
|
||||
pub device_model: Option<String>,
|
||||
pub os_version: Option<String>,
|
||||
pub locale_code: String,
|
||||
pub device_platform: String,
|
||||
events: EventsStore,
|
||||
users: UsersStore,
|
||||
sessions: SessionsStore,
|
||||
}
|
||||
|
||||
impl AppState {
|
||||
@@ -54,49 +37,63 @@ impl AppState {
|
||||
started_at: Instant::now(),
|
||||
database_pool,
|
||||
redis_client,
|
||||
current_user_id: Uuid::new_v4(),
|
||||
session: Arc::new(RwLock::new(None)),
|
||||
events: EventsStore::new(),
|
||||
users: UsersStore::new(),
|
||||
sessions: SessionsStore::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn start_session(&self, request: SessionStartRequest) -> SessionSnapshot {
|
||||
let session = SessionSnapshot {
|
||||
session_id: Uuid::new_v4(),
|
||||
user_id: self.current_user_id,
|
||||
started_at: Utc::now(),
|
||||
ended_at: None,
|
||||
experiment_variant: request
|
||||
.experiment_variant
|
||||
.unwrap_or_else(|| self.config.default_experiment_variant.clone()),
|
||||
app_version: request
|
||||
.app_version
|
||||
.unwrap_or_else(|| self.config.app_version.clone()),
|
||||
device_model: request.device_model,
|
||||
os_version: request.os_version,
|
||||
locale_code: request
|
||||
.locale_code
|
||||
.unwrap_or_else(|| self.config.default_locale.clone()),
|
||||
device_platform: request
|
||||
.device_platform
|
||||
.unwrap_or_else(|| self.config.default_device_platform.clone()),
|
||||
};
|
||||
let user = self
|
||||
.users
|
||||
.upsert(UserCreateRequest {
|
||||
external_ref: request.external_ref.clone(),
|
||||
preferred_language: request
|
||||
.locale_code
|
||||
.clone()
|
||||
.unwrap_or_else(|| self.config.default_locale.clone()),
|
||||
device_platform: request
|
||||
.device_platform
|
||||
.clone()
|
||||
.unwrap_or_else(|| self.config.default_device_platform.clone()),
|
||||
})
|
||||
.await;
|
||||
|
||||
*self.session.write().await = Some(session.clone());
|
||||
session
|
||||
self.sessions
|
||||
.start_session(
|
||||
user.id,
|
||||
request,
|
||||
SessionDefaults {
|
||||
default_locale: self.config.default_locale.clone(),
|
||||
default_device_platform: self.config.default_device_platform.clone(),
|
||||
default_app_version: self.config.app_version.clone(),
|
||||
default_experiment_variant: self.config.default_experiment_variant.clone(),
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn current_session(&self) -> Option<SessionSnapshot> {
|
||||
self.session.read().await.clone()
|
||||
self.sessions.current_session().await
|
||||
}
|
||||
|
||||
pub async fn end_session(&self) -> Result<SessionSnapshot, AppError> {
|
||||
let mut guard = self.session.write().await;
|
||||
let mut session = guard
|
||||
.clone()
|
||||
.ok_or_else(|| AppError::not_found("No active session"))?;
|
||||
session.ended_at = Some(Utc::now());
|
||||
*guard = Some(session.clone());
|
||||
Ok(session)
|
||||
self.sessions
|
||||
.end_session()
|
||||
.await
|
||||
.map_err(|_| AppError::not_found("No active session"))
|
||||
}
|
||||
|
||||
pub async fn next_event(&self) -> Option<EventSnapshot> {
|
||||
self.events.next_event().await
|
||||
}
|
||||
|
||||
pub async fn event(&self, event_id: Uuid) -> Option<EventSnapshot> {
|
||||
self.events.get_event(event_id).await
|
||||
}
|
||||
|
||||
pub async fn event_manifest(&self, event_id: Uuid) -> Option<EventManifestSnapshot> {
|
||||
self.events.get_manifest(event_id).await
|
||||
}
|
||||
|
||||
pub fn database_ready(&self) -> bool {
|
||||
|
||||
Reference in New Issue
Block a user