indradb_utils.rs (6019B)
1 use std::{ 2 collections::{BTreeMap, VecDeque}, 3 mem::replace, 4 }; 5 6 use color_eyre::Result; 7 use lazy_static::lazy_static; 8 use matrix_sdk::ruma::{OwnedEventId, OwnedRoomId}; 9 use tokio::task::JoinHandle; 10 use utils::{ 11 indradb::{self, BulkInsertItem}, 12 indradb_proto as proto, 13 }; 14 use uuid::{Context, Uuid}; 15 16 const REQUEST_BUFFER_SIZE: usize = 10_000; 17 18 lazy_static! { 19 static ref CONTEXT: Context = Context::new(0); 20 } 21 22 pub struct BulkInserter { 23 requests: async_channel::Sender<Vec<indradb::BulkInsertItem>>, 24 workers: Vec<JoinHandle<Result<()>>>, 25 buf: Vec<indradb::BulkInsertItem>, 26 client: proto::Client, 27 } 28 29 impl BulkInserter { 30 pub fn new(client: proto::Client) -> Self { 31 let (tx, rx) = async_channel::bounded::<Vec<indradb::BulkInsertItem>>(10); 32 let mut workers = Vec::default(); 33 34 for _ in 0..10 { 35 let rx = rx.clone(); 36 let mut client = client.clone(); 37 workers.push(tokio::spawn(async move { 38 while let Ok(buf) = rx.recv().await { 39 client.bulk_insert(buf).await?; 40 } 41 Ok(()) 42 })); 43 } 44 45 Self { 46 client, 47 requests: tx, 48 workers, 49 buf: Vec::with_capacity(REQUEST_BUFFER_SIZE), 50 } 51 } 52 53 pub async fn sync(&mut self) -> Result<()> { 54 self.client.sync().await?; 55 Ok(()) 56 } 57 58 pub async fn flush(&mut self) -> Result<()> { 59 if !self.buf.is_empty() { 60 self.requests.send(self.buf.clone()).await?; 61 } 62 //self.requests.close(); 63 // for worker in &self.workers { 64 // worker.await??; 65 // } 66 self.sync().await?; 67 Ok(()) 68 } 69 70 pub async fn push(&mut self, item: indradb::BulkInsertItem) -> Result<()> { 71 self.buf.push(item); 72 if self.buf.len() >= REQUEST_BUFFER_SIZE { 73 let buf = replace(&mut self.buf, Vec::with_capacity(REQUEST_BUFFER_SIZE)); 74 self.requests.send(buf).await?; 75 } 76 Ok(()) 77 } 78 } 79 80 #[derive(Clone)] 81 pub struct UUIDEventMapType { 82 pub event_id: OwnedEventId, 83 pub uuid: EventUuid, 84 pub event_type: utils::indradb::Identifier, 85 pub event_properties: EventProperties, 86 } 87 88 #[derive(Clone)] 89 pub struct UUIDRoomMapType { 90 pub room_id: OwnedRoomId, 91 pub uuid: RoomUuid, 92 pub room_properties: RoomProperties, 93 } 94 95 #[derive(Clone)] 96 pub enum EventProperties { 97 TextMessage(String, Option<String>, Option<String>), 98 } 99 100 #[derive(Clone)] 101 pub struct RoomProperties { 102 pub name: Option<String>, 103 pub topic: Option<String>, 104 } 105 106 pub type RoomUuid = Uuid; 107 pub type EventUuid = Uuid; 108 109 // TODO: Track all the properties! 110 #[derive(Default)] 111 pub struct MessagesMap { 112 event_uuids: BTreeMap<OwnedEventId, EventUuid>, 113 pub message_list: VecDeque<UUIDEventMapType>, 114 room_uuids: BTreeMap<OwnedRoomId, RoomUuid>, 115 pub room_list: VecDeque<UUIDRoomMapType>, 116 pub room_event_links: BTreeMap<EventUuid, RoomUuid>, 117 } 118 119 impl EventProperties { 120 pub fn as_vec(&self, uuid: Uuid) -> Result<Vec<BulkInsertItem>> { 121 match self { 122 EventProperties::TextMessage(body, format, formatted_body) => { 123 let mut vector = Vec::with_capacity(3); 124 vector.push(utils::indradb::BulkInsertItem::VertexProperty( 125 uuid, 126 utils::indradb::Identifier::new("text_message_body")?, 127 serde_json::Value::String(body.to_string()).into(), 128 )); 129 if let Some(format) = format { 130 vector.push(utils::indradb::BulkInsertItem::VertexProperty( 131 uuid, 132 utils::indradb::Identifier::new("text_message_format")?, 133 serde_json::Value::String(format.to_string()).into(), 134 )); 135 } 136 if let Some(formatted_body) = formatted_body { 137 vector.push(utils::indradb::BulkInsertItem::VertexProperty( 138 uuid, 139 utils::indradb::Identifier::new("text_message_formatted_body")?, 140 serde_json::Value::String(formatted_body.to_string()).into(), 141 )); 142 } 143 144 Ok(vector) 145 } 146 } 147 } 148 } 149 150 impl MessagesMap { 151 pub fn insert_event( 152 &mut self, 153 event_id: OwnedEventId, 154 room_uuid: RoomUuid, 155 event_type: utils::indradb::Identifier, 156 event_properties: EventProperties, 157 ) -> EventUuid { 158 // FIXME: We need to actually look them up here to get the uuid since we index live. 159 // This means the uuid list might not have all events when we are indexing reactions. 160 if let Some(&uuid) = self.event_uuids.get(&event_id) { 161 return uuid; 162 } 163 164 let uuid = Uuid::new_v4(); 165 let map_thingy = UUIDEventMapType { 166 event_id: event_id.clone(), 167 uuid, 168 event_type, 169 event_properties, 170 }; 171 self.event_uuids.insert(event_id, uuid); 172 self.message_list.push_back(map_thingy); 173 self.room_event_links.insert(uuid, room_uuid); 174 uuid 175 } 176 177 pub fn insert_room( 178 &mut self, 179 room_id: OwnedRoomId, 180 room_properties: RoomProperties, 181 ) -> RoomUuid { 182 // FIXME: We need to actually look them up here to get the uuid since we index live. 183 // This means the uuid list might not have all events when we are indexing reactions. 184 // FIXME: we probably need to also make updates for roomnames and topic here 185 if let Some(&uuid) = self.room_uuids.get(&room_id) { 186 return uuid; 187 } 188 189 let uuid = Uuid::new_v4(); 190 let map_thingy = UUIDRoomMapType { 191 room_id: room_id.clone(), 192 uuid, 193 room_properties, 194 }; 195 self.room_uuids.insert(room_id, uuid); 196 self.room_list.push_back(map_thingy); 197 uuid 198 } 199 }