use crate::future::FdbValue;
use crate::options::TransactionOption;
use crate::{FdbBindingError, FdbResult, KeySelector, RangeOption, Transaction};
use foundationdb_tuple::{pack, unpack};
use futures::StreamExt;
const TIME_KEEPER_PREFIX: &[u8] = b"\xff\x02/timeKeeper/map/";
pub enum HintMode {
BeforeTimestamp,
AfterTimestamp,
}
pub async fn hint_version_from_timestamp(
trx: &Transaction,
unix_timestamp_as_seconds: u64,
mode: HintMode,
snapshot: bool,
) -> Result<Option<u64>, FdbBindingError> {
trx.set_option(TransactionOption::ReadSystemKeys)?;
trx.set_option(TransactionOption::ReadLockAware)?;
let mut start_key_bytes = TIME_KEEPER_PREFIX.to_vec();
start_key_bytes.extend_from_slice(&pack(&unix_timestamp_as_seconds));
let start_key = KeySelector::first_greater_or_equal(start_key_bytes.clone());
let mut end_key_bytes = TIME_KEEPER_PREFIX.to_vec();
end_key_bytes.extend_from_slice(b"\xff");
let end_key = KeySelector::first_greater_than(end_key_bytes);
let mut range = match mode {
HintMode::AfterTimestamp => RangeOption::from((start_key, end_key)),
HintMode::BeforeTimestamp => {
let mut range = RangeOption::from((
KeySelector::first_greater_than(TIME_KEEPER_PREFIX),
start_key,
));
range.reverse = true;
range
}
};
range.limit = Some(1);
let results = trx
.get_ranges_keyvalues(range, snapshot)
.take(1)
.collect::<Vec<FdbResult<FdbValue>>>()
.await;
if let Some(Ok(kv)) = results.first() {
let version = unpack(kv.value()).map_err(FdbBindingError::PackError)?;
return Ok(Some(version));
}
Ok(None)
}