knowledge-search

git clone git://archive.git.mtrnord.blog/MTRNord/knowledge-search.git
Log | Files | Refs | README | LICENSE

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 }