use async_trait::async_trait;
use super::{db_schema, Session, SessionError, SessionId, SessionService};
use crate::events::Event;
#[derive(Debug, Clone)]
pub struct PostgresSessionConfig {
pub connection_string: String,
pub max_connections: u32,
}
impl PostgresSessionConfig {
pub fn new(connection_string: impl Into<String>) -> Self {
Self {
connection_string: connection_string.into(),
max_connections: 10,
}
}
pub fn max_connections(mut self, max: u32) -> Self {
self.max_connections = max;
self
}
}
pub struct PostgresSessionService {
config: PostgresSessionConfig,
}
impl PostgresSessionService {
pub fn new(config: PostgresSessionConfig) -> Self {
Self { config }
}
pub async fn initialize(&self) -> Result<(), SessionError> {
let _schema = db_schema::POSTGRES_SCHEMA;
let _conn_str = &self.config.connection_string;
let _max_conns = self.config.max_connections;
todo!("Connect to PostgreSQL at {_conn_str} and run POSTGRES_SCHEMA migration")
}
pub fn connection_string(&self) -> &str {
&self.config.connection_string
}
pub fn max_connections(&self) -> u32 {
self.config.max_connections
}
}
#[async_trait]
impl SessionService for PostgresSessionService {
async fn create_session(&self, app_name: &str, user_id: &str) -> Result<Session, SessionError> {
let session = Session::new(app_name, user_id);
let _id = session.id.as_str();
let _state = serde_json::to_value(&session.state)
.map_err(|e| SessionError::Storage(e.to_string()))?;
todo!("INSERT session {_id} into PostgreSQL")
}
async fn get_session(&self, id: &SessionId) -> Result<Option<Session>, SessionError> {
let _id = id.as_str();
todo!("SELECT session {_id} from PostgreSQL")
}
async fn list_sessions(
&self,
app_name: &str,
user_id: &str,
) -> Result<Vec<Session>, SessionError> {
let _app = app_name;
let _user = user_id;
todo!("SELECT sessions for app={_app} user={_user} from PostgreSQL")
}
async fn delete_session(&self, id: &SessionId) -> Result<(), SessionError> {
let _id = id.as_str();
todo!("DELETE session {_id} from PostgreSQL")
}
async fn append_event(&self, id: &SessionId, event: Event) -> Result<(), SessionError> {
let _session_id = id.as_str();
let _event_id = &event.id;
let _invocation_id = &event.invocation_id;
let _author = &event.author;
let _content = &event.content;
let _actions = serde_json::to_value(&event.actions)
.map_err(|e| SessionError::Storage(e.to_string()))?;
let _timestamp = event.timestamp;
todo!("INSERT event {_event_id} for session {_session_id} into PostgreSQL")
}
async fn get_events(&self, id: &SessionId) -> Result<Vec<Event>, SessionError> {
let _id = id.as_str();
todo!("SELECT events for session {_id} from PostgreSQL")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn config_new() {
let config = PostgresSessionConfig::new("postgres://localhost/test");
assert_eq!(config.connection_string, "postgres://localhost/test");
assert_eq!(config.max_connections, 10);
}
#[test]
fn config_max_connections() {
let config = PostgresSessionConfig::new("postgres://localhost/test").max_connections(20);
assert_eq!(config.max_connections, 20);
}
#[test]
fn service_accessors() {
let svc = PostgresSessionService::new(
PostgresSessionConfig::new("postgres://user:pass@host/db").max_connections(5),
);
assert_eq!(svc.connection_string(), "postgres://user:pass@host/db");
assert_eq!(svc.max_connections(), 5);
}
}