feat: Introduce smart-features Cargo feature to conditionally compile smart note functionalities and their dependencies.

This commit is contained in:
2025-12-26 00:48:03 +01:00
parent c8276ac306
commit c2a324b368
12 changed files with 144 additions and 60 deletions

View File

@@ -3,11 +3,17 @@ name = "notes-worker"
version = "0.1.0"
edition = "2024"
[features]
default = ["sqlite", "smart-features"]
sqlite = ["notes-infra/sqlite", "sqlx/sqlite"]
# postgres = ["notes-infra/postgres", "sqlx/postgres"]
smart-features = ["notes-infra/smart-features"]
[dependencies]
anyhow = "1.0.100"
async-nats = "0.45.0"
notes-domain = { path = "../notes-domain" }
notes-infra = { path = "../notes-infra" }
notes-infra = { path = "../notes-infra", default-features = false }
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.146"
tokio = { version = "1.48.0", features = ["full"] }

View File

@@ -1,10 +1,13 @@
#[cfg(feature = "smart-features")]
use notes_infra::factory::{EmbeddingProvider, VectorProvider};
#[derive(Debug, Clone)]
pub struct Config {
pub broker_url: String,
pub database_url: String,
#[cfg(feature = "smart-features")]
pub embedding_provider: EmbeddingProvider,
#[cfg(feature = "smart-features")]
pub vector_provider: VectorProvider,
}
@@ -13,7 +16,9 @@ impl Default for Config {
Self {
broker_url: "nats://localhost:4222".to_string(),
database_url: "sqlite::memory:".to_string(),
#[cfg(feature = "smart-features")]
embedding_provider: EmbeddingProvider::FastEmbed,
#[cfg(feature = "smart-features")]
vector_provider: VectorProvider::Qdrant {
url: "http://localhost:6334".to_string(),
collection: "notes".to_string(),
@@ -26,6 +31,7 @@ impl Config {
pub fn from_env() -> Self {
let _ = dotenvy::dotenv();
#[cfg(feature = "smart-features")]
let embedding_provider = match std::env::var("EMBEDDING_PROVIDER")
.unwrap_or_default()
.as_str()
@@ -33,6 +39,7 @@ impl Config {
_ => EmbeddingProvider::FastEmbed,
};
#[cfg(feature = "smart-features")]
let vector_provider = match std::env::var("VECTOR_PROVIDER")
.unwrap_or_default()
.as_str()
@@ -48,7 +55,9 @@ impl Config {
Self {
broker_url: std::env::var("BROKER_URL").unwrap_or("nats://localhost:4222".to_string()),
database_url: std::env::var("DATABASE_URL").unwrap_or("sqlite::memory:".to_string()),
#[cfg(feature = "smart-features")]
embedding_provider,
#[cfg(feature = "smart-features")]
vector_provider,
}
}

View File

@@ -1,5 +1,7 @@
use futures_util::StreamExt;
#[cfg(feature = "smart-features")]
use notes_domain::services::SmartNoteService;
#[cfg(feature = "smart-features")]
use notes_infra::{
DatabaseConfig,
factory::{
@@ -25,42 +27,51 @@ async fn main() -> anyhow::Result<()> {
let config = Config::from_env();
let nats_client = async_nats::connect(&config.broker_url).await?;
let db_config = DatabaseConfig::new(config.database_url.clone());
let db_pool = build_database_pool(&db_config).await?;
// Initialize smart feature adapters
let embedding_generator = build_embedding_generator(&config.embedding_provider).await?;
let vector_store = build_vector_store(&config.vector_provider).await?;
let link_repo = build_link_repository(&db_pool).await?;
#[cfg(feature = "smart-features")]
{
let db_config = DatabaseConfig::new(config.database_url.clone());
let db_pool = build_database_pool(&db_config).await?;
// Create the service
let smart_service = SmartNoteService::new(embedding_generator, vector_store, link_repo);
tracing::info!(
"SmartNoteService initialized successfully with {:?}",
config.embedding_provider
);
// Initialize smart feature adapters
let embedding_generator = build_embedding_generator(&config.embedding_provider).await?;
let vector_store = build_vector_store(&config.vector_provider).await?;
let link_repo = build_link_repository(&db_pool).await?;
// Subscribe to note update events
let mut subscriber = nats_client.subscribe("notes.updated").await?;
tracing::info!("Worker listening on 'notes.updated'...");
// Create the service
let smart_service = SmartNoteService::new(embedding_generator, vector_store, link_repo);
tracing::info!(
"SmartNoteService initialized successfully with {:?}",
config.embedding_provider
);
while let Some(msg) = subscriber.next().await {
// Parse message payload (assuming the payload IS the Note JSON)
let note_result: Result<notes_domain::Note, _> = serde_json::from_slice(&msg.payload);
// Subscribe to note update events
let mut subscriber = nats_client.subscribe("notes.updated").await?;
tracing::info!("Worker listening on 'notes.updated'...");
match note_result {
Ok(note) => {
tracing::info!("Processing smart features for note: {}", note.id);
match smart_service.process_note(&note).await {
Ok(_) => tracing::info!("Successfully processed note {}", note.id),
Err(e) => tracing::error!("Failed to process note {}: {}", note.id, e),
while let Some(msg) = subscriber.next().await {
// Parse message payload (assuming the payload IS the Note JSON)
let note_result: Result<notes_domain::Note, _> = serde_json::from_slice(&msg.payload);
match note_result {
Ok(note) => {
tracing::info!("Processing smart features for note: {}", note.id);
match smart_service.process_note(&note).await {
Ok(_) => tracing::info!("Successfully processed note {}", note.id),
Err(e) => tracing::error!("Failed to process note {}: {}", note.id, e),
}
}
Err(e) => {
tracing::error!("Failed to deserialize note from message: {}", e);
}
}
Err(e) => {
tracing::error!("Failed to deserialize note from message: {}", e);
}
}
}
#[cfg(not(feature = "smart-features"))]
{
tracing::info!("Smart features are disabled. Worker will exit.");
}
Ok(())
}