feat: Implement NATS-based event processing for note smart features and add Qdrant collection auto-creation.

This commit is contained in:
2025-12-26 00:19:41 +01:00
parent 178d59540e
commit 64f8118228
11 changed files with 155 additions and 6 deletions

View File

@@ -20,6 +20,7 @@ tower-sessions-sqlx-store = { version = "0.15", features = ["sqlite"] }
password-auth = "1.0"
time = "0.3"
async-trait = "0.1.89"
async-nats = "0.39"
# Async runtime
tokio = { version = "1.48.0", features = ["full"] }

View File

@@ -12,6 +12,7 @@ pub struct Config {
pub allow_registration: bool,
pub embedding_provider: EmbeddingProvider,
pub vector_provider: VectorProvider,
pub broker_url: String,
}
impl Default for Config {
@@ -29,6 +30,7 @@ impl Default for Config {
url: "http://localhost:6334".to_string(),
collection: "notes".to_string(),
},
broker_url: "nats://localhost:4222".to_string(),
}
}
}
@@ -77,6 +79,9 @@ impl Config {
},
};
let broker_url =
env::var("BROKER_URL").unwrap_or_else(|_| "nats://localhost:4222".to_string());
Self {
host,
port,
@@ -86,6 +91,7 @@ impl Config {
allow_registration,
embedding_provider,
vector_provider,
broker_url,
}
}
}

View File

@@ -80,6 +80,12 @@ async fn main() -> anyhow::Result<()> {
let tag_service = Arc::new(TagService::new(tag_repo.clone()));
let user_service = Arc::new(UserService::new(user_repo.clone()));
// Connect to NATS
tracing::info!("Connecting to NATS: {}", config.broker_url);
let nats_client = async_nats::connect(&config.broker_url)
.await
.map_err(|e| anyhow::anyhow!("NATS connection failed: {}", e))?;
// Create application state
let state = AppState::new(
note_repo,
@@ -88,6 +94,7 @@ async fn main() -> anyhow::Result<()> {
note_service,
tag_service,
user_service,
nats_client,
config.clone(),
);

View File

@@ -82,6 +82,18 @@ pub async fn create_note(
let note = state.note_service.create_note(domain_req).await?;
// Publish event
let payload = serde_json::to_vec(&note).unwrap_or_default();
if let Err(e) = state
.nats_client
.publish("notes.updated", payload.into())
.await
{
tracing::error!("Failed to publish notes.updated event: {}", e);
} else {
tracing::info!("Published notes.updated event for note {}", note.id);
}
Ok((StatusCode::CREATED, Json(NoteResponse::from(note))))
}
@@ -137,6 +149,18 @@ pub async fn update_note(
let note = state.note_service.update_note(domain_req).await?;
// Publish event
let payload = serde_json::to_vec(&note).unwrap_or_default();
if let Err(e) = state
.nats_client
.publish("notes.updated", payload.into())
.await
{
tracing::error!("Failed to publish notes.updated event: {}", e);
} else {
tracing::info!("Published notes.updated event for note {}", note.id);
}
Ok(Json(NoteResponse::from(note)))
}

View File

@@ -14,6 +14,7 @@ pub struct AppState {
pub note_service: Arc<NoteService>,
pub tag_service: Arc<TagService>,
pub user_service: Arc<UserService>,
pub nats_client: async_nats::Client,
pub config: Config,
}
@@ -25,6 +26,7 @@ impl AppState {
note_service: Arc<NoteService>,
tag_service: Arc<TagService>,
user_service: Arc<UserService>,
nats_client: async_nats::Client,
config: Config,
) -> Self {
Self {
@@ -34,6 +36,7 @@ impl AppState {
note_service,
tag_service,
user_service,
nats_client,
config,
}
}