uni_db/api/hooks.rs
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2024-2026 Dragonscale Team
3
4//! Session hooks — before/after interception for queries and commits.
5//!
6//! Hooks allow cross-cutting concerns (audit logging, authorization, metrics)
7//! to be injected into the query and commit lifecycle without modifying
8//! individual query call sites.
9
10use std::collections::HashMap;
11
12use uni_common::{Result, Value};
13use uni_query::QueryMetrics;
14
15use crate::api::transaction::CommitResult;
16
17/// The type of query being executed.
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum QueryType {
20 /// A Cypher query (read or write).
21 Cypher,
22 /// A Locy program evaluation.
23 Locy,
24 /// An execute (mutation) statement.
25 Execute,
26}
27
28/// Context passed to query hooks.
29#[derive(Debug, Clone)]
30pub struct HookContext {
31 /// The session ID that initiated the query.
32 pub session_id: String,
33 /// The query text (Cypher or Locy program).
34 pub query_text: String,
35 /// The type of query.
36 pub query_type: QueryType,
37 /// Parameters bound to the query.
38 pub params: HashMap<String, Value>,
39}
40
41/// Context passed to commit hooks.
42#[derive(Debug, Clone)]
43pub struct CommitHookContext {
44 /// The session ID that owns the transaction.
45 pub session_id: String,
46 /// The transaction ID being committed.
47 pub tx_id: String,
48 /// Number of mutations in the transaction.
49 pub mutation_count: usize,
50}
51
52/// Trait for session lifecycle hooks.
53///
54/// Implement this trait to intercept queries and commits at the session level.
55/// Hooks are stored as `Arc<dyn SessionHook>` and can be shared across sessions
56/// and templates.
57///
58/// # Failure Semantics
59///
60/// - `before_query`: Returning `Err` aborts the query with `HookRejected`.
61/// - `after_query`: Infallible — panics are caught and logged.
62/// - `before_commit`: Returning `Err` aborts the commit with `HookRejected`.
63/// - `after_commit`: Infallible — panics are caught and logged.
64pub trait SessionHook: Send + Sync {
65 /// Called before a query is executed. Return `Err` to reject the query.
66 fn before_query(&self, _ctx: &HookContext) -> Result<()> {
67 Ok(())
68 }
69
70 /// Called after a query completes. Panics are caught and logged.
71 fn after_query(&self, _ctx: &HookContext, _metrics: &QueryMetrics) {}
72
73 /// Called before a transaction is committed. Return `Err` to reject the commit.
74 fn before_commit(&self, _ctx: &CommitHookContext) -> Result<()> {
75 Ok(())
76 }
77
78 /// Called after a transaction is successfully committed. Panics are caught and logged.
79 fn after_commit(&self, _ctx: &CommitHookContext, _result: &CommitResult) {}
80}