Skip to main content

fraiseql_cli/config/toml_schema/
caching.rs

1//! Caching and analytics configuration for TOML schema.
2
3use serde::{Deserialize, Serialize};
4
5/// Declarative result-cache rules (#623).
6///
7/// Rules are **lowered at compile time** onto the two compiled fields the
8/// runtime's result cache already consumes: the named query's
9/// `cache_ttl_seconds` (the per-view TTL map) and each trigger mutation's
10/// `invalidates_views` (mutation-driven invalidation). Runtime enablement
11/// remains the server's `cache_enabled`.
12#[derive(Debug, Clone, Deserialize, Serialize)]
13#[serde(default, deny_unknown_fields)]
14pub struct CachingConfig {
15    /// Gate for the rules below: `true` with rules lowers them; `false` with
16    /// rules — or `true` without rules — is refused at compile time.
17    #[serde(default)]
18    pub enabled:   bool,
19    /// Cache backend. Only `"memory"` exists — the runtime result cache is
20    /// in-process; any other value is refused at compile time.
21    pub backend:   String,
22    /// Refused at compile time: there is no Redis-backed result cache.
23    pub redis_url: Option<String>,
24    /// Per-query cache rules.
25    pub rules:     Vec<CacheRule>,
26}
27
28impl Default for CachingConfig {
29    fn default() -> Self {
30        Self {
31            enabled:   false,
32            backend:   "memory".to_string(),
33            redis_url: None,
34            rules:     vec![],
35        }
36    }
37}
38
39/// One declarative cache rule (#623).
40#[derive(Debug, Clone, Deserialize, Serialize)]
41#[serde(deny_unknown_fields)]
42pub struct CacheRule {
43    /// Name of an existing query (compile error otherwise).
44    pub query:                 String,
45    /// TTL lowered onto the query's `cache_ttl_seconds`. A query that already
46    /// declares one (SDK/JSON-authored) is a compile error — two authoring
47    /// sources must not silently last-write-win.
48    pub ttl_seconds:           u32,
49    /// Names of existing mutations (compile error otherwise) whose success
50    /// must invalidate this query's cached results; each gains the query's
51    /// view in its `invalidates_views`.
52    pub invalidation_triggers: Vec<String>,
53}
54
55/// Analytics query definitions (#624).
56///
57/// Each entry is **lowered at compile time into an ordinary compiled query**:
58/// an operator-authored, compile-validated `sql_source` (a view, typically an
59/// aggregate/materialized one) served with the SELECT list of its declared
60/// `return_type`. No client-supplied identifier can reach `FROM` or the
61/// SELECT list because neither exists on this path at request time.
62#[derive(Debug, Clone, Default, Deserialize, Serialize)]
63#[serde(default, deny_unknown_fields)]
64pub struct AnalyticsConfig {
65    /// Gate for the queries below: `true` with queries lowers them; `false`
66    /// with queries — or `true` without queries — is refused at compile time.
67    #[serde(default)]
68    pub enabled: bool,
69    /// Analytics query definitions.
70    pub queries: Vec<AnalyticsQuery>,
71}
72
73/// One analytics query (#624), compiled into a list-returning view query.
74#[derive(Debug, Clone, Deserialize, Serialize)]
75#[serde(deny_unknown_fields)]
76pub struct AnalyticsQuery {
77    /// GraphQL field name. Must not collide with an existing query and must
78    /// not end in `_aggregate` / `_window` (the executor classifies those
79    /// suffixes before query resolution, so such a query would be
80    /// unreachable).
81    pub name:        String,
82    /// Declared type whose fields form the SELECT list (compile error if the
83    /// type does not exist).
84    pub return_type: String,
85    /// The view to serve — validated as a SQL identifier at compile time
86    /// (reject, never escape).
87    pub sql_source:  String,
88    /// Query description.
89    pub description: Option<String>,
90}