feedsignal/crates/db/src/affinities.rs
Austin Schaefer 0612d642c9
All checks were successful
CI / check (pull_request) Successful in 2m16s
CI / test (pull_request) Successful in 4m13s
CI / audit (pull_request) Successful in 15s
Split db crate into per-domain modules (feeds/articles/reading_events/affinities)
feedsignal-db's Db impl had grown into one 250-line block mixing feed
subscriptions, article storage/scoring, reading-event logging, and
topic-affinity persistence in a single file. Split each domain's
methods into its own module (mirroring the earlier web crate SRP
split), keeping lib.rs to just the Db struct and connection setup.
Pure move — no behavior or public API changes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QmwX8eafbMstJvt8XPSqft
2026-09-03 13:32:19 +02:00

43 lines
1.4 KiB
Rust

use crate::schema;
use crate::Db;
use anyhow::Result;
use chrono::Utc;
use diesel::prelude::*;
use diesel_async::RunQueryDsl;
use feedsignal_core::TopicAffinities;
impl Db {
pub async fn load_affinities(&self) -> Result<TopicAffinities> {
use schema::topic_affinities::dsl;
let mut conn = self.pool.get().await?;
let row: Option<String> = dsl::topic_affinities
.filter(dsl::user_id.eq("default"))
.select(dsl::affinities)
.first(&mut conn)
.await
.optional()?;
Ok(match row {
Some(json) => serde_json::from_str(&json)?,
None => TopicAffinities::default(),
})
}
pub async fn save_affinities(&self, affinities: &TopicAffinities) -> Result<()> {
use schema::topic_affinities::dsl;
let mut conn = self.pool.get().await?;
let json = serde_json::to_string(affinities)?;
let updated_at = Utc::now().to_rfc3339();
diesel::insert_into(dsl::topic_affinities)
.values((
dsl::user_id.eq("default"),
dsl::affinities.eq(&json),
dsl::updated_at.eq(&updated_at),
))
.on_conflict(dsl::user_id)
.do_update()
.set((dsl::affinities.eq(&json), dsl::updated_at.eq(&updated_at)))
.execute(&mut conn)
.await?;
Ok(())
}
}