use std::path::PathBuf;
use std::sync::Arc;
use tokio::sync::RwLock;
use mongodb::{Client, Database};
use tokio_util::sync::CancellationToken;
use crate::connection::ConnectionManager;
use crate::error::Result;
use crate::repl::SharedState;
#[derive(Clone)]
pub struct ExecutionContext {
connection: Arc<RwLock<ConnectionManager>>,
pub(crate) shared_state: SharedState,
pub(crate) config_path: Option<PathBuf>,
client_id: Arc<String>,
cancel_token: CancellationToken,
}
impl ExecutionContext {
pub fn new(connection: ConnectionManager, shared_state: SharedState) -> Self {
Self::with_config_path(connection, shared_state, None)
}
pub fn with_config_path(
connection: ConnectionManager,
shared_state: SharedState,
config_path: Option<PathBuf>,
) -> Self {
let client_id = Self::generate_client_id();
Self {
connection: Arc::new(RwLock::new(connection)),
shared_state,
config_path,
client_id: Arc::new(client_id),
cancel_token: CancellationToken::new(),
}
}
fn generate_client_id() -> String {
use std::time::{SystemTime, UNIX_EPOCH};
let hostname = hostname::get()
.ok()
.and_then(|h| h.into_string().ok())
.unwrap_or_else(|| "unknown".to_string());
let pid = std::process::id();
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs();
format!("{}-{}-{}", hostname, pid, timestamp)
}
pub async fn get_current_database(&self) -> String {
self.shared_state.get_database()
}
pub async fn set_current_database(&self, database: String) {
let mut state = self.shared_state.clone();
state.set_database(database);
}
pub async fn get_database(&self) -> Result<Database> {
let conn = self.connection.read().await;
let db_name = self.shared_state.get_database();
conn.get_database(&db_name)
}
pub async fn get_client(&self) -> Result<Client> {
let conn = self.connection.read().await;
Ok(conn.get_client()?.clone())
}
pub fn get_client_id(&self) -> &str {
&self.client_id
}
pub fn get_cancel_token(&self) -> CancellationToken {
self.cancel_token.clone()
}
pub fn reset_cancel_token(&mut self) {
self.cancel_token = CancellationToken::new();
}
}