feat: centralize NATS message broker implementation in infra and abstract its usage in API and worker
This commit is contained in:
@@ -16,7 +16,7 @@ postgres = [
|
||||
"tower-sessions-sqlx-store/postgres",
|
||||
"sqlx/postgres",
|
||||
]
|
||||
smart-features = ["notes-infra/smart-features", "dep:async-nats"]
|
||||
smart-features = ["notes-infra/smart-features", "notes-infra/broker-nats"]
|
||||
|
||||
[dependencies]
|
||||
notes-domain = { path = "../notes-domain" }
|
||||
@@ -36,7 +36,6 @@ tower-sessions-sqlx-store = { version = "0.15", features = ["sqlite"] }
|
||||
password-auth = "1.0"
|
||||
time = "0.3"
|
||||
async-trait = "0.1.89"
|
||||
async-nats = { version = "0.39", optional = true }
|
||||
|
||||
# Async runtime
|
||||
tokio = { version = "1.48.0", features = ["full"] }
|
||||
|
||||
@@ -18,8 +18,6 @@ mod auth;
|
||||
mod config;
|
||||
mod dto;
|
||||
mod error;
|
||||
#[cfg(feature = "smart-features")]
|
||||
mod nats_broker;
|
||||
mod routes;
|
||||
mod state;
|
||||
|
||||
@@ -81,13 +79,17 @@ async fn main() -> anyhow::Result<()> {
|
||||
.await
|
||||
.map_err(|e| anyhow::anyhow!(e))?;
|
||||
|
||||
// Connect to NATS (before creating services that depend on it)
|
||||
// Connect to message broker via factory
|
||||
#[cfg(feature = "smart-features")]
|
||||
let nats_client = {
|
||||
tracing::info!("Connecting to NATS: {}", config.broker_url);
|
||||
async_nats::connect(&config.broker_url)
|
||||
let message_broker = {
|
||||
use notes_infra::factory::{BrokerProvider, build_message_broker};
|
||||
tracing::info!("Connecting to message broker: {}", config.broker_url);
|
||||
let provider = BrokerProvider::Nats {
|
||||
url: config.broker_url.clone(),
|
||||
};
|
||||
build_message_broker(&provider)
|
||||
.await
|
||||
.map_err(|e| anyhow::anyhow!("NATS connection failed: {}", e))?
|
||||
.map_err(|e| anyhow::anyhow!("Broker connection failed: {}", e))?
|
||||
};
|
||||
|
||||
// Create services
|
||||
@@ -95,9 +97,11 @@ async fn main() -> anyhow::Result<()> {
|
||||
|
||||
// Build NoteService with optional MessageBroker
|
||||
#[cfg(feature = "smart-features")]
|
||||
let note_service = {
|
||||
let broker = Arc::new(nats_broker::NatsMessageBroker::new(nats_client.clone()));
|
||||
Arc::new(NoteService::new(note_repo.clone(), tag_repo.clone()).with_message_broker(broker))
|
||||
let note_service = match message_broker {
|
||||
Some(broker) => Arc::new(
|
||||
NoteService::new(note_repo.clone(), tag_repo.clone()).with_message_broker(broker),
|
||||
),
|
||||
None => Arc::new(NoteService::new(note_repo.clone(), tag_repo.clone())),
|
||||
};
|
||||
#[cfg(not(feature = "smart-features"))]
|
||||
let note_service = Arc::new(NoteService::new(note_repo.clone(), tag_repo.clone()));
|
||||
@@ -115,8 +119,6 @@ async fn main() -> anyhow::Result<()> {
|
||||
note_service,
|
||||
tag_service,
|
||||
user_service,
|
||||
#[cfg(feature = "smart-features")]
|
||||
nats_client,
|
||||
config.clone(),
|
||||
);
|
||||
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
//! NATS message broker adapter for domain MessageBroker port
|
||||
|
||||
use async_trait::async_trait;
|
||||
use notes_domain::{DomainError, DomainResult, MessageBroker, Note};
|
||||
|
||||
/// NATS adapter implementing the MessageBroker port
|
||||
pub struct NatsMessageBroker {
|
||||
client: async_nats::Client,
|
||||
}
|
||||
|
||||
impl NatsMessageBroker {
|
||||
pub fn new(client: async_nats::Client) -> Self {
|
||||
Self { client }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl MessageBroker for NatsMessageBroker {
|
||||
async fn publish_note_updated(&self, note: &Note) -> DomainResult<()> {
|
||||
let payload = serde_json::to_vec(note).map_err(|e| {
|
||||
DomainError::RepositoryError(format!("Failed to serialize note: {}", e))
|
||||
})?;
|
||||
|
||||
self.client
|
||||
.publish("notes.updated", payload.into())
|
||||
.await
|
||||
.map_err(|e| DomainError::RepositoryError(format!("Failed to publish event: {}", e)))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,6 @@ pub struct AppState {
|
||||
pub note_service: Arc<NoteService>,
|
||||
pub tag_service: Arc<TagService>,
|
||||
pub user_service: Arc<UserService>,
|
||||
#[cfg(feature = "smart-features")]
|
||||
pub nats_client: async_nats::Client,
|
||||
pub config: Config,
|
||||
}
|
||||
|
||||
@@ -30,7 +28,6 @@ impl AppState {
|
||||
note_service: Arc<NoteService>,
|
||||
tag_service: Arc<TagService>,
|
||||
user_service: Arc<UserService>,
|
||||
#[cfg(feature = "smart-features")] nats_client: async_nats::Client,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
Self {
|
||||
@@ -42,8 +39,6 @@ impl AppState {
|
||||
note_service,
|
||||
tag_service,
|
||||
user_service,
|
||||
#[cfg(feature = "smart-features")]
|
||||
nats_client,
|
||||
config,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user