Skip to main content

khive_runtime/atomic_prepare/
post_commit.rs

1use super::{
2    apply_post_commit_effects_with_failures, note_reindex_effect, CommittedPostCommitEffects,
3    KhiveRuntime, NamespaceToken, PostCommitEffect, PostCommitEmbeddingOutcome, RuntimeResult,
4};
5
6/// Run every deferred [`PostCommitEffect`] after a committed atomic unit.
7pub async fn apply_post_commit_effects(
8    runtime: &KhiveRuntime,
9    token: &NamespaceToken,
10    effects: CommittedPostCommitEffects,
11) -> RuntimeResult<()> {
12    apply_post_commit_effects_with_report(runtime, token, effects)
13        .await
14        .map(|_| ())
15}
16
17/// Embedding-reporting form of [`apply_post_commit_effects`]. Re-fetches each
18/// target's now-committed row outside any transaction and reuses the existing
19/// `reindex_entity`/`reindex_note` (FTS + embedding, same as the non-atomic
20/// path) for exact parity. Returns the typed embedding outcome for each reindex
21/// effect so callers can preserve truncation advisories and partial model
22/// failures instead of discarding them after commit. Model failures remain
23/// best-effort; lexical indexing and excluded-model cleanup errors propagate.
24/// When any effect fails, the other effects' outcomes are dropped with the
25/// returned error; [`apply_post_commit_effects_with_failures`] keeps both.
26pub async fn apply_post_commit_effects_with_report(
27    runtime: &KhiveRuntime,
28    token: &NamespaceToken,
29    effects: CommittedPostCommitEffects,
30) -> RuntimeResult<Vec<PostCommitEmbeddingOutcome>> {
31    let report = apply_post_commit_effects_with_failures(runtime, token, effects).await;
32    match report.failure_error() {
33        Some(error) => Err(error),
34        None => Ok(report.outcomes),
35    }
36}
37
38pub(super) async fn apply_one_post_commit_effect(
39    runtime: &KhiveRuntime,
40    token: &NamespaceToken,
41    effect: PostCommitEffect,
42) -> RuntimeResult<Option<PostCommitEmbeddingOutcome>> {
43    match effect {
44        PostCommitEffect::None => Ok(None),
45        PostCommitEffect::NoteChanged { note_id, kind } => {
46            runtime.fire_note_mutation_hook(&kind, note_id).await;
47            Ok(None)
48        }
49        PostCommitEffect::ReindexEntity { entity_id } => {
50            let Some(entity) = runtime.entities(token)?.get_entity(entity_id).await? else {
51                return Ok(None);
52            };
53            let truncation = runtime.reindex_entity(token, &entity).await?;
54            Ok(Some(PostCommitEmbeddingOutcome {
55                effect: PostCommitEffect::ReindexEntity { entity_id },
56                truncation,
57                failures: Vec::new(),
58            }))
59        }
60        PostCommitEffect::ReindexNote { note_id, version } => {
61            note_reindex_effect::apply(runtime, token, note_id, version).await
62        }
63        PostCommitEffect::NoteDeleted { note_id, kind } => {
64            // The committed row may already be gone; use the captured kind.
65            runtime.fire_note_mutation_hook(&kind, note_id).await;
66            Ok(None)
67        }
68        PostCommitEffect::GtdAudit { .. } => {
69            // The kkernel caller owns the GTD pack's separate audit side write.
70            Ok(None)
71        }
72    }
73}