drasi_core/interface/index_backend.rs
1// Copyright 2025 The Drasi Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Index Backend Plugin Trait
16//!
17//! This module defines the `IndexBackendPlugin` trait that external index backends
18//! (like RocksDB, Garnet/Redis) must implement to integrate with Drasi.
19//!
20//! # Architecture
21//!
22//! The index plugin system follows pure dependency inversion:
23//! - **Core** provides index traits (`ElementIndex`, `ResultIndex`, etc.) and a default
24//! in-memory implementation
25//! - **Lib** uses this plugin trait but has no knowledge of specific implementations
26//! - **External plugins** (in `components/indexes/`) implement this trait
27//! - **Applications** optionally inject plugins; if none provided, the in-memory default is used
28
29use async_trait::async_trait;
30use std::fmt;
31use std::sync::Arc;
32
33use super::{
34 ElementArchiveIndex, ElementIndex, FutureQueue, IndexError, ResultIndex, SessionControl,
35};
36
37/// Set of indexes for a query.
38///
39/// Groups the index types and session control needed for query evaluation into
40/// a single unit.
41/// This enables backends to create all indexes from a shared underlying resource
42/// (e.g., a single RocksDB instance or Redis connection).
43pub struct IndexSet {
44 /// Element index for storing graph elements
45 pub element_index: Arc<dyn ElementIndex>,
46 /// Archive index for storing historical elements (for past() function)
47 pub archive_index: Arc<dyn ElementArchiveIndex>,
48 /// Result index for storing query results
49 pub result_index: Arc<dyn ResultIndex>,
50 /// Future queue for temporal queries
51 pub future_queue: Arc<dyn FutureQueue>,
52 /// Session control for atomic transaction lifecycle
53 pub session_control: Arc<dyn SessionControl>,
54}
55
56impl fmt::Debug for IndexSet {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 f.debug_struct("IndexSet")
59 .field("element_index", &"<trait object>")
60 .field("archive_index", &"<trait object>")
61 .field("result_index", &"<trait object>")
62 .field("future_queue", &"<trait object>")
63 .field("session_control", &"<trait object>")
64 .finish()
65 }
66}
67
68/// Plugin trait for external index storage backends.
69///
70/// Each storage backend (RocksDB, Garnet, etc.) implements this trait to provide
71/// all index types needed for query evaluation from a single shared backend instance.
72///
73/// # Thread Safety
74///
75/// Implementations must be `Send + Sync` to allow use across async tasks.
76///
77/// # Example
78///
79/// ```ignore
80/// use drasi_core::interface::{IndexBackendPlugin, IndexSet};
81///
82/// pub struct MyIndexProvider {
83/// // configuration fields
84/// }
85///
86/// #[async_trait]
87/// impl IndexBackendPlugin for MyIndexProvider {
88/// async fn create_index_set(&self, query_id: &str) -> Result<IndexSet, IndexError> {
89/// // Create and return all indexes from a shared backend instance
90/// }
91/// fn is_volatile(&self) -> bool { false }
92/// }
93/// ```
94#[async_trait]
95pub trait IndexBackendPlugin: Send + Sync {
96 /// Create all indexes for a query from a single shared backend instance.
97 ///
98 /// This method creates the element index, archive index, result index,
99 /// future queue, and session control backed by a shared storage resource
100 /// (e.g., a single RocksDB database or Redis connection). This reduces
101 /// resource overhead and enables cross-index atomic transactions.
102 async fn create_index_set(&self, query_id: &str) -> Result<IndexSet, IndexError>;
103
104 /// Returns true if this backend is volatile (data lost on restart).
105 ///
106 /// Volatile backends (like in-memory) require re-bootstrapping after restart,
107 /// while persistent backends (like RocksDB) retain data.
108 fn is_volatile(&self) -> bool;
109}