use tracing::debug;
use super::types::KvGetParams;
use crate::bridge::envelope::Response;
use crate::data::executor::core_loop::CoreLoop;
use crate::data::executor::handlers::transaction::overlay::{Staged, StagedTtl};
use crate::data::executor::handlers::transaction::stage_write::hex_key;
use crate::data::executor::task::ExecutionTask;
use crate::engine::kv::current_ms;
use crate::types::TenantId;
impl CoreLoop {
pub(in crate::data::executor) fn execute_kv_get(
&self,
task: &ExecutionTask,
params: KvGetParams<'_>,
) -> Response {
let KvGetParams {
did,
tid,
collection,
key,
rls_filters,
surrogate_ceiling,
} = params;
debug!(core = self.core_id, %collection, "kv get");
if let Some(txn_id) = task.request.txn_id {
self.touch_overlay(txn_id);
let coll_key = (
task.request.database_id,
TenantId::new(tid),
collection.to_string(),
);
let doc_id = hex_key(key);
if let Some(overlay) = self.txn_overlays.get(&txn_id) {
if matches!(
overlay.get_ttl_by_doc_id(&coll_key, &doc_id),
Some(StagedTtl::ExpireAt(t)) if t <= current_ms()
) {
return self.response_with_payload(task, Vec::new());
}
if let Some(staged) = overlay.get_by_doc_id(&coll_key, &doc_id) {
return match staged {
Staged::Put(body) => {
if !crate::data::executor::handlers::rls_eval::rls_check_msgpack_bytes(
rls_filters,
body,
) {
self.response_with_payload(task, Vec::new())
} else {
self.response_with_payload(task, body.clone())
}
}
Staged::Tombstone => self.response_with_payload(task, Vec::new()),
};
}
}
}
let now_ms = current_ms();
let fetched = match surrogate_ceiling {
Some(ceiling) => {
self.kv_engine
.get_with_surrogate(did, tid, collection, key, now_ms)
.and_then(|(value, surrogate)| {
let s = surrogate.as_u32();
if s != 0 && s > ceiling {
None
} else {
Some(value)
}
})
}
None => self.kv_engine.get(did, tid, collection, key, now_ms),
};
match fetched {
Some(value) => {
if !crate::data::executor::handlers::rls_eval::rls_check_msgpack_bytes(
rls_filters,
&value,
) {
return self.response_with_payload(task, Vec::new());
}
if let Some(ref m) = self.metrics {
m.record_kv_get();
}
self.response_with_payload(task, value)
}
None => self.response_with_payload(task, Vec::new()),
}
}
}