diff --git a/Cargo.lock b/Cargo.lock index 930ace50f..0f21f2a83 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -302,6 +302,7 @@ dependencies = [ "libc", "num-integer", "num-traits", + "serde", "time", "winapi 0.3.9", ] @@ -1277,6 +1278,7 @@ dependencies = [ "anyhow", "bstr", "byteorder", + "chrono", "criterion", "crossbeam-channel", "csv", diff --git a/milli/Cargo.toml b/milli/Cargo.toml index 2eb40dc94..b63e34b32 100644 --- a/milli/Cargo.toml +++ b/milli/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" anyhow = "1.0.38" bstr = "0.2.15" byteorder = "1.4.2" +chrono = { version = "0.4.19", features = ["serde"] } crossbeam-channel = "0.5.0" csv = "1.1.5" either = "1.6.1" diff --git a/milli/src/index.rs b/milli/src/index.rs index c0a00080e..c7a855e1f 100644 --- a/milli/src/index.rs +++ b/milli/src/index.rs @@ -6,6 +6,7 @@ use anyhow::Context; use heed::types::*; use heed::{PolyDatabase, Database, RwTxn, RoTxn}; use roaring::RoaringBitmap; +use chrono::{Utc, DateTime}; use crate::facet::FacetType; use crate::fields_ids_map::FieldsIdsMap; @@ -28,6 +29,8 @@ pub const HARD_EXTERNAL_DOCUMENTS_IDS_KEY: &str = "hard-external-documents-ids"; pub const SOFT_EXTERNAL_DOCUMENTS_IDS_KEY: &str = "soft-external-documents-ids"; pub const WORDS_FST_KEY: &str = "words-fst"; pub const WORDS_PREFIXES_FST_KEY: &str = "words-prefixes-fst"; +const CREATED_AT_KEY: &str = "created-at"; +const UPDATED_AT_KEY: &str ="updated-at"; #[derive(Clone)] pub struct Index { @@ -68,6 +71,17 @@ impl Index { let field_id_docid_facet_values = env.create_database(Some("field-id-docid-facet-values"))?; let documents = env.create_database(Some("documents"))?; + { + let mut txn = env.write_txn()?; + // The db was just created, we update its metadata with the relevant information. + if main.get::<_, Str, SerdeJson>>(&txn, CREATED_AT_KEY)?.is_none() { + let now = Utc::now(); + main.put::<_, Str, SerdeJson>>(&mut txn, UPDATED_AT_KEY, &now)?; + main.put::<_, Str, SerdeJson>>(&mut txn, CREATED_AT_KEY, &now)?; + txn.commit()?; + } + } + Ok(Index { env, main, @@ -393,4 +407,24 @@ impl Index { pub fn search<'a>(&'a self, rtxn: &'a RoTxn) -> Search<'a> { Search::new(rtxn, self) } + + /// Returns the index creation time. + pub fn created_at(&self, rtxn: &RoTxn) -> heed::Result> { + let time = self.main + .get::<_, Str, SerdeJson>>(rtxn, CREATED_AT_KEY)? + .expect("Index without creation time"); + Ok(time) + } + + /// Returns the index creation time. + pub fn updated_at(&self, rtxn: &RoTxn) -> heed::Result> { + let time = self.main + .get::<_, Str, SerdeJson>>(rtxn, UPDATED_AT_KEY)? + .expect("Index without update time"); + Ok(time) + } + + pub(crate) fn set_updated_at(&self, wtxn: &mut RwTxn, time: &DateTime) -> heed::Result<()> { + self.main.put::<_, Str, SerdeJson>>(wtxn, UPDATED_AT_KEY, &time) + } }