Feature/unified nl search #106
@@ -84,32 +84,26 @@ impl UserAiPrefsDao for SqliteUserAiPrefsDao {
|
|||||||
.lock()
|
.lock()
|
||||||
.expect("Unable to lock UserAiPrefsDao");
|
.expect("Unable to lock UserAiPrefsDao");
|
||||||
|
|
||||||
// SQLite: INSERT on first call, UPDATE on subsequent calls.
|
// Single-row table (id=1): one atomic upsert. The explicit id=1
|
||||||
// The first INSERT creates the row with id=1 (auto-increment).
|
// makes the conflict target deterministic so the second call
|
||||||
// Subsequent calls UPDATE the existing row.
|
// updates in place rather than tripping the CHECK(id=1) constraint,
|
||||||
let result = diesel::insert_into(dsl::user_ai_prefs)
|
// and real insert errors surface instead of being swallowed into a
|
||||||
.values(prefs)
|
// separate update branch. The columns are set explicitly (rather
|
||||||
.execute(connection.deref_mut());
|
// than via AsChangeset) so a None field overwrites to NULL — the
|
||||||
|
// row mirrors the latest request exactly, not a merge of past ones.
|
||||||
match result {
|
diesel::insert_into(dsl::user_ai_prefs)
|
||||||
Ok(_) => {
|
.values((dsl::id.eq(1), prefs))
|
||||||
// First insert succeeded.
|
.on_conflict(dsl::id)
|
||||||
Ok(())
|
.do_update()
|
||||||
}
|
.set((
|
||||||
Err(_e) => {
|
dsl::voice.eq(&prefs.voice),
|
||||||
// Insert failed (likely due to duplicate key). Update instead.
|
dsl::tz_offset_minutes.eq(&prefs.tz_offset_minutes),
|
||||||
diesel::update(dsl::user_ai_prefs.filter(dsl::id.eq(1)))
|
dsl::library.eq(&prefs.library),
|
||||||
.set((
|
dsl::updated_at.eq(&prefs.updated_at),
|
||||||
dsl::voice.eq(&prefs.voice),
|
))
|
||||||
dsl::tz_offset_minutes.eq(&prefs.tz_offset_minutes),
|
.execute(connection.deref_mut())
|
||||||
dsl::library.eq(&prefs.library),
|
.map_err(|e| anyhow::anyhow!("Failed to upsert prefs: {}", e))?;
|
||||||
dsl::updated_at.eq(&prefs.updated_at),
|
Ok(())
|
||||||
))
|
|
||||||
.execute(connection.deref_mut())
|
|
||||||
.map_err(|e| anyhow::anyhow!("Failed to upsert prefs: {}", e))?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.map_err(|e| DbError::log(DbErrorKind::InsertError, e))
|
.map_err(|e| DbError::log(DbErrorKind::InsertError, e))
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -1075,6 +1075,8 @@ async fn pregen_one(
|
|||||||
// Flatten every media item across beats (in order) into the cache key.
|
// Flatten every media item across beats (in order) into the cache key.
|
||||||
let media: Vec<SegmentMedia> = planned.iter().flat_map(|b| b.media.clone()).collect();
|
let media: Vec<SegmentMedia> = planned.iter().flat_map(|b| b.media.clone()).collect();
|
||||||
let key = cache_key(&selector, &media, voice.as_deref());
|
let key = cache_key(&selector, &media, voice.as_deref());
|
||||||
|
// Total media items shown (photos + clips), not beat count.
|
||||||
|
let media_count = media.len() as i32;
|
||||||
|
|
||||||
// Dedup: check if fresh ledger row exists
|
// Dedup: check if fresh ledger row exists
|
||||||
let now = std::time::SystemTime::now()
|
let now = std::time::SystemTime::now()
|
||||||
@@ -1127,7 +1129,7 @@ async fn pregen_one(
|
|||||||
cache_key: key.clone(),
|
cache_key: key.clone(),
|
||||||
output_path: mp4_path.to_string_lossy().to_string(),
|
output_path: mp4_path.to_string_lossy().to_string(),
|
||||||
title,
|
title,
|
||||||
media_count: planned.len() as i32,
|
media_count,
|
||||||
render_version: RENDER_VERSION as i32,
|
render_version: RENDER_VERSION as i32,
|
||||||
tz_offset_minutes: tz,
|
tz_offset_minutes: tz,
|
||||||
voice: voice.clone(),
|
voice: voice.clone(),
|
||||||
@@ -1139,7 +1141,6 @@ async fn pregen_one(
|
|||||||
|
|
||||||
// Generate the reel
|
// Generate the reel
|
||||||
log::info!("Generating precomputed reel for span={}, key={}", span, key);
|
log::info!("Generating precomputed reel for span={}, key={}", span, key);
|
||||||
let photo_count = planned.len() as i32;
|
|
||||||
let (title, mp4) = produce_reel(
|
let (title, mp4) = produce_reel(
|
||||||
app_state,
|
app_state,
|
||||||
insight_dao,
|
insight_dao,
|
||||||
@@ -1163,7 +1164,7 @@ async fn pregen_one(
|
|||||||
cache_key: key.clone(),
|
cache_key: key.clone(),
|
||||||
output_path: mp4.to_string_lossy().to_string(),
|
output_path: mp4.to_string_lossy().to_string(),
|
||||||
title,
|
title,
|
||||||
media_count: photo_count,
|
media_count,
|
||||||
render_version: RENDER_VERSION as i32,
|
render_version: RENDER_VERSION as i32,
|
||||||
tz_offset_minutes: tz,
|
tz_offset_minutes: tz,
|
||||||
voice: voice.clone(),
|
voice: voice.clone(),
|
||||||
|
|||||||
Reference in New Issue
Block a user