matrix_sdk_search/index/
builder.rs1use std::{
2 fs,
3 path::{Path, PathBuf},
4 sync::Arc,
5};
6
7use ruma::OwnedRoomId;
8use tantivy::{
9 Index,
10 directory::{MmapDirectory, error::OpenDirectoryError},
11};
12use tracing::warn;
13use zeroize::Zeroizing;
14
15use crate::{
16 encrypted::encrypted_dir::EncryptedMmapDirectory,
17 error::IndexError,
18 index::RoomIndex,
19 schema::{MatrixSearchIndexSchema, RoomMessageSchema},
20};
21
22pub struct RoomIndexBuilder {}
24
25impl RoomIndexBuilder {
26 pub fn new_on_disk<R: Into<OwnedRoomId>>(
28 path: PathBuf,
29 room_id: R,
30 ) -> PhysicalRoomIndexBuilder {
31 PhysicalRoomIndexBuilder::new(path, room_id.into())
32 }
33
34 pub fn new_in_memory<R: Into<OwnedRoomId>>(room_id: R) -> MemoryRoomIndexBuilder {
36 MemoryRoomIndexBuilder::new(room_id.into())
37 }
38}
39
40pub struct PhysicalRoomIndexBuilder {
42 path: PathBuf,
43 room_id: OwnedRoomId,
44}
45
46impl PhysicalRoomIndexBuilder {
47 pub(crate) fn new(path: PathBuf, room_id: OwnedRoomId) -> PhysicalRoomIndexBuilder {
49 PhysicalRoomIndexBuilder { path, room_id }
50 }
51
52 pub fn unencrypted(&self) -> UnencryptedPhysicalRoomIndexBuilder {
54 UnencryptedPhysicalRoomIndexBuilder {
55 path: self.path.clone(),
56 room_id: self.room_id.clone(),
57 }
58 }
59
60 pub fn encrypted<K: Into<String>>(&self, key: K) -> EncryptedPhysicalRoomIndexBuilder {
62 EncryptedPhysicalRoomIndexBuilder {
63 path: self.path.clone(),
64 room_id: self.room_id.clone(),
65 key: Zeroizing::new(key.into()),
66 }
67 }
68}
69
70pub struct UnencryptedPhysicalRoomIndexBuilder {
72 path: PathBuf,
73 room_id: OwnedRoomId,
74}
75
76impl UnencryptedPhysicalRoomIndexBuilder {
77 pub fn build(&self) -> Result<RoomIndex, IndexError> {
79 let path = self.path.join(self.room_id.as_str());
80 let mmap_dir = match MmapDirectory::open(path) {
81 Ok(dir) => Ok(dir),
82 Err(err) => match err {
83 OpenDirectoryError::DoesNotExist(path) => {
84 fs::create_dir_all(path.clone()).map_err(|err| {
85 OpenDirectoryError::IoError {
86 io_error: Arc::new(err),
87 directory_path: path.to_path_buf(),
88 }
89 })?;
90 MmapDirectory::open(path)
91 }
92 _ => Err(err),
93 },
94 }?;
95 let schema = RoomMessageSchema::new();
96 let index = Index::open_or_create(mmap_dir, schema.as_tantivy_schema())?;
97 Ok(RoomIndex::new_with(index, schema, &self.room_id))
98 }
99}
100
101pub struct EncryptedPhysicalRoomIndexBuilder {
103 path: PathBuf,
104 room_id: OwnedRoomId,
105 key: Zeroizing<String>,
106}
107
108impl EncryptedPhysicalRoomIndexBuilder {
109 pub fn build(&self) -> Result<RoomIndex, IndexError> {
114 let path = self.path.join(self.room_id.as_str());
115
116 self.open(&path).or_else(|err| {
119 warn!(room_id = %self.room_id, "Recreating the search index: {err}");
120 fs::remove_dir_all(&path)?;
121 self.open(&path)
122 })
123 }
124
125 fn open(&self, path: &Path) -> Result<RoomIndex, IndexError> {
126 let mmap_dir = EncryptedMmapDirectory::open_or_create(path, &self.key)?;
127 let schema = RoomMessageSchema::new();
128 let index = Index::open_or_create(mmap_dir, schema.as_tantivy_schema())?;
129 Ok(RoomIndex::new_with(index, schema, &self.room_id))
130 }
131}
132
133pub struct MemoryRoomIndexBuilder {
135 room_id: OwnedRoomId,
136}
137
138impl MemoryRoomIndexBuilder {
139 pub(crate) fn new(room_id: OwnedRoomId) -> MemoryRoomIndexBuilder {
141 MemoryRoomIndexBuilder { room_id }
142 }
143
144 pub fn build(&self) -> RoomIndex {
146 let schema = RoomMessageSchema::new();
147 let index = Index::create_in_ram(schema.as_tantivy_schema());
148 RoomIndex::new_with(index, schema, &self.room_id)
149 }
150}