feat: init
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::cache::AppCache;
|
||||
use crate::cache::redis::AppRedis;
|
||||
use crate::config::AppConfig;
|
||||
use crate::error::AppError;
|
||||
use crate::etcd::EtcdRegistry;
|
||||
use crate::models::db::AppDatabase;
|
||||
use crate::queue::NatsQueue;
|
||||
use crate::service::im::events::ImEventBus;
|
||||
use crate::storage::s3::AppS3Storage;
|
||||
|
||||
/// Shared infrastructure context for all domain services.
|
||||
///
|
||||
/// Each sub-service (Auth, User, Workspace, Repo) holds an `Arc<ServiceContext>`
|
||||
/// so they share the same database, cache, and other infrastructure without
|
||||
/// duplicating ownership.
|
||||
#[derive(Clone)]
|
||||
pub struct ServiceContext {
|
||||
pub version: String,
|
||||
pub db: AppDatabase,
|
||||
pub redis: AppRedis,
|
||||
pub cache: Arc<AppCache>,
|
||||
pub config: AppConfig,
|
||||
pub storage: AppS3Storage,
|
||||
/// etcd-based service registry for discovering git and mail RPC services.
|
||||
pub registry: Arc<EtcdRegistry>,
|
||||
/// NATS JetStream queue for real-time event broadcasting.
|
||||
pub nats: Arc<NatsQueue>,
|
||||
pub im_events: Arc<ImEventBus>,
|
||||
}
|
||||
|
||||
impl ServiceContext {
|
||||
/// Run a block of work inside a database transaction.
|
||||
///
|
||||
/// - Begins a transaction on the writer pool
|
||||
/// - Sets `app.current_user_id` for RLS / audit triggers
|
||||
/// - Commits on success, rolls back on error
|
||||
pub async fn run_in_transaction<F, Fut, T>(&self, user_uid: Uuid, f: F) -> Result<T, AppError>
|
||||
where
|
||||
F: FnOnce(&mut sqlx::Transaction<'_, sqlx::Postgres>) -> Fut,
|
||||
Fut: std::future::Future<Output = Result<T, AppError>>,
|
||||
{
|
||||
let mut txn = self
|
||||
.db
|
||||
.writer()
|
||||
.begin()
|
||||
.await
|
||||
.map_err(|_| AppError::TxnError)?;
|
||||
|
||||
sqlx::query("SET LOCAL app.current_user_id = $1")
|
||||
.bind(user_uid)
|
||||
.execute(&mut *txn)
|
||||
.await
|
||||
.map_err(AppError::Database)?;
|
||||
|
||||
let result = f(&mut txn).await?;
|
||||
|
||||
txn.commit().await.map_err(|_| AppError::TxnError)?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user