MeiliSearch/meilidb-core/src/store/updates.rs

105 lines
2.9 KiB
Rust
Raw Normal View History

2019-10-03 16:39:30 +02:00
use std::convert::TryInto;
use rkv::Value;
2019-10-03 17:33:15 +02:00
use crate::{update::Update, MResult};
2019-10-03 15:04:11 +02:00
#[derive(Copy, Clone)]
pub struct Updates {
pub(crate) updates: rkv::SingleStore,
}
impl Updates {
2019-10-03 16:39:30 +02:00
// TODO we should use the MDB_LAST op but
// it is not exposed by the rkv library
2019-10-04 10:21:09 +02:00
fn last_update_id<'a>(
2019-10-03 16:39:30 +02:00
&self,
2019-10-04 10:21:09 +02:00
reader: &'a impl rkv::Readable,
2019-10-03 16:39:30 +02:00
) -> Result<Option<(u64, Option<Value<'a>>)>, rkv::StoreError>
{
let mut last = None;
let iter = self.updates.iter_start(reader)?;
for result in iter {
let (key, data) = result?;
last = Some((key, data));
}
let (last_key, last_data) = match last {
Some(entry) => entry,
None => return Ok(None),
};
let array = last_key.try_into().unwrap();
let number = u64::from_be_bytes(array);
Ok(Some((number, last_data)))
}
fn first_update_id<'a>(
&self,
reader: &'a impl rkv::Readable,
) -> Result<Option<(u64, Option<Value<'a>>)>, rkv::StoreError>
{
let mut iter = self.updates.iter_start(reader)?;
let (first_key, first_data) = match iter.next() {
Some(result) => result?,
None => return Ok(None),
};
let array = first_key.try_into().unwrap();
let number = u64::from_be_bytes(array);
Ok(Some((number, first_data)))
}
2019-10-04 10:21:09 +02:00
pub fn contains(
2019-10-03 16:54:37 +02:00
&self,
2019-10-04 10:21:09 +02:00
reader: &impl rkv::Readable,
2019-10-03 16:54:37 +02:00
update_id: u64,
) -> Result<bool, rkv::StoreError>
{
let update_id_bytes = update_id.to_be_bytes();
self.updates.get(reader, update_id_bytes).map(|v| v.is_some())
}
2019-10-03 15:04:11 +02:00
pub fn push_back(
&self,
writer: &mut rkv::Writer,
update: &Update,
2019-10-03 17:33:15 +02:00
) -> MResult<u64>
2019-10-03 15:04:11 +02:00
{
2019-10-03 16:39:30 +02:00
let last_update_id = self.last_update_id(writer)?;
let last_update_id = last_update_id.map_or(0, |(n, _)| n + 1);
let last_update_id_bytes = last_update_id.to_be_bytes();
2019-10-03 16:13:09 +02:00
2019-10-03 17:33:15 +02:00
let update = rmp_serde::to_vec_named(&update)?;
2019-10-03 16:39:30 +02:00
let blob = Value::Blob(&update);
self.updates.put(writer, last_update_id_bytes, &blob)?;
2019-10-03 16:13:09 +02:00
2019-10-03 16:39:30 +02:00
Ok(last_update_id)
2019-10-03 15:04:11 +02:00
}
pub fn pop_front(
2019-10-03 15:04:11 +02:00
&self,
2019-10-03 16:13:09 +02:00
writer: &mut rkv::Writer,
2019-10-03 17:33:15 +02:00
) -> MResult<Option<(u64, Update)>>
2019-10-03 15:04:11 +02:00
{
let (last_id, last_data) = match self.first_update_id(writer)? {
2019-10-03 16:39:30 +02:00
Some(entry) => entry,
None => return Ok(None),
};
match last_data {
Some(Value::Blob(bytes)) => {
2019-10-03 17:33:15 +02:00
let update = rmp_serde::from_read_ref(&bytes)?;
// remove it from the database now
let last_id_bytes = last_id.to_be_bytes();
self.updates.delete(writer, last_id_bytes)?;
2019-10-03 16:39:30 +02:00
Ok(Some((last_id, update)))
},
Some(value) => panic!("invalid type {:?}", value),
None => Ok(None),
}
2019-10-03 15:04:11 +02:00
}
}