use crate::{
admission::scope::{AttemptExecutionManifest, AttemptExecutionScope, AttemptProducerOccurrence},
error::{QueryError, QueryErrorCode, Result},
plan::{DeferredGraphExecutionScopeIdentity, PlanFingerprint, QueryPlan, SchemaFingerprint},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ExecutionCapability {
name: &'static str,
}
impl ExecutionCapability {
pub const fn new(name: &'static str) -> Self {
Self { name }
}
pub(crate) const fn as_str(self) -> &'static str {
self.name
}
}
pub const CUGRAPH_GRAPH_EXECUTION_CAPABILITY: ExecutionCapability = ExecutionCapability::new("cugraph_graph_execution");
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct AttestedCugraphGraphExecutionScope {
pub(crate) execution_scope_fingerprint: PlanFingerprint,
pub(crate) deferred_execution_scope_identity: Option<DeferredGraphExecutionScopeIdentity>,
}
impl AttestedCugraphGraphExecutionScope {
pub(crate) fn for_plan(plan: &QueryPlan) -> Self {
Self { execution_scope_fingerprint: plan.execution_fingerprint(), deferred_execution_scope_identity: None }
}
pub(crate) fn matches(&self, plan: &QueryPlan) -> bool {
self.execution_scope_fingerprint == plan.execution_fingerprint()
|| self.deferred_execution_scope_identity.as_ref().is_some_and(|scope| scope.matches(plan))
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct AttemptCapabilityEvidence {
#[doc(hidden)]
pub required_capabilities: Vec<ExecutionCapability>,
pub(crate) attested_cugraph_graph_execution_scopes: Vec<AttestedCugraphGraphExecutionScope>,
pub(crate) execution_scopes: Vec<AttemptExecutionScope>,
pub(crate) execution_manifest: Option<AttemptExecutionManifest>,
}
impl AttemptCapabilityEvidence {
#[doc(hidden)]
pub fn empty() -> Self {
Self::default()
}
#[doc(hidden)]
pub fn for_query_plan(plan: &QueryPlan) -> Self {
Self {
required_capabilities: Vec::new(),
attested_cugraph_graph_execution_scopes: Vec::new(),
execution_scopes: vec![AttemptExecutionScope::for_query_plan(plan)],
execution_manifest: None,
}
}
#[cfg(any(test, feature = "test-hooks"))]
#[doc(hidden)]
pub fn from_parts(
required_capabilities: Vec<ExecutionCapability>,
execution_scopes: Vec<AttemptExecutionScope>,
) -> Self {
Self {
required_capabilities,
attested_cugraph_graph_execution_scopes: Vec::new(),
execution_scopes,
execution_manifest: None,
}
}
#[cfg(any(test, feature = "test-hooks"))]
#[doc(hidden)]
pub fn required_capabilities(&self) -> &[ExecutionCapability] {
&self.required_capabilities
}
#[doc(hidden)]
pub fn execution_scopes(&self) -> &[AttemptExecutionScope] {
&self.execution_scopes
}
#[doc(hidden)]
pub fn execution_manifest(&self) -> Option<&AttemptExecutionManifest> {
self.execution_manifest.as_ref()
}
#[doc(hidden)]
pub fn deferred_graph_identity_for_scope(
&self,
execution_scope_fingerprint: PlanFingerprint,
) -> Option<DeferredGraphExecutionScopeIdentity> {
self.attested_cugraph_graph_execution_scopes
.iter()
.find(|scope| scope.execution_scope_fingerprint == execution_scope_fingerprint)
.and_then(|scope| scope.deferred_execution_scope_identity.clone())
}
#[doc(hidden)]
pub fn without_execution_manifest(mut self) -> Self {
self.execution_manifest = None;
self
}
#[doc(hidden)]
pub fn with_execution_manifest(mut self, manifest: AttemptExecutionManifest) -> Result<Self> {
if self.execution_manifest.is_some() {
return Err(duplicate_execution_manifest_error());
}
self.execution_manifest = Some(manifest);
Ok(self)
}
#[doc(hidden)]
pub fn attest_cugraph_graph_execution_scope(&mut self, plan: &QueryPlan) {
if !self.required_capabilities.contains(&CUGRAPH_GRAPH_EXECUTION_CAPABILITY) {
self.required_capabilities.push(CUGRAPH_GRAPH_EXECUTION_CAPABILITY);
}
let scope = AttestedCugraphGraphExecutionScope::for_plan(plan);
if !self.attested_cugraph_graph_execution_scopes.contains(&scope) {
self.attested_cugraph_graph_execution_scopes.push(scope);
}
}
#[doc(hidden)]
pub fn attest_deferred_cugraph_graph_execution_scope(&mut self, plan: &QueryPlan) {
self.attest_cugraph_graph_execution_scope(plan);
let exact = plan.execution_fingerprint();
if let Some(scope) = self
.attested_cugraph_graph_execution_scopes
.iter_mut()
.find(|scope| scope.execution_scope_fingerprint == exact)
{
scope.deferred_execution_scope_identity = Some(DeferredGraphExecutionScopeIdentity::for_plan(plan));
}
}
#[doc(hidden)]
pub fn push_producer_occurrence(&mut self, occurrence: AttemptProducerOccurrence) -> Result<()> {
let Some(scope) = self.execution_scopes.last_mut() else {
return Err(QueryError::new(
QueryErrorCode::InternalInvariantViolation,
"query_engine.admission.evidence",
"a producer occurrence has no admitted consumer scope to bind to",
)
.with_fact("reason", "missing_consumer_scope"));
};
scope.push_producer_occurrence(occurrence);
Ok(())
}
#[doc(hidden)]
pub fn covers(&self, fragment: &Self) -> bool {
fragment.required_capabilities.iter().all(|capability| self.required_capabilities.contains(capability))
&& fragment
.attested_cugraph_graph_execution_scopes
.iter()
.all(|scope| self.attested_cugraph_graph_execution_scopes.contains(scope))
&& fragment.execution_scopes.iter().all(|scope| self.execution_scopes.contains(scope))
&& fragment
.execution_manifest
.as_ref()
.is_none_or(|manifest| self.execution_manifest.as_ref() == Some(manifest))
}
#[doc(hidden)]
pub fn aggregate<I: IntoIterator<Item = Self>>(evidence: I) -> Result<Self> {
let mut aggregate = Self::empty();
for one in evidence {
if one.execution_manifest.is_some() && aggregate.execution_manifest.is_some() {
return Err(duplicate_execution_manifest_error());
}
aggregate.union(&one);
}
Ok(aggregate)
}
#[doc(hidden)]
pub fn join(&mut self, fragment: &Self) -> Result<()> {
if let (Some(bound), Some(manifest)) = (&self.execution_manifest, &fragment.execution_manifest)
&& bound != manifest
{
return Err(duplicate_execution_manifest_error());
}
self.union(fragment);
Ok(())
}
fn union(&mut self, other: &Self) {
for capability in &other.required_capabilities {
if !self.required_capabilities.contains(capability) {
self.required_capabilities.push(*capability);
}
}
for scope in &other.attested_cugraph_graph_execution_scopes {
if !self.attested_cugraph_graph_execution_scopes.contains(scope) {
self.attested_cugraph_graph_execution_scopes.push(scope.clone());
}
}
for scope in &other.execution_scopes {
if !self.execution_scopes.contains(scope) {
self.execution_scopes.push(scope.clone());
}
}
if self.execution_manifest.is_none() {
self.execution_manifest.clone_from(&other.execution_manifest);
}
}
#[doc(hidden)]
pub fn producer_occurrence_scope_count_for_plan(&self, plan: &QueryPlan) -> usize {
let execution_scope = plan.execution_fingerprint();
self.execution_scopes.iter().map(|scope| scope.producer_occurrence_scope_count(execution_scope)).sum()
}
#[doc(hidden)]
pub fn validate_composed_occurrences(&self, plan: &QueryPlan, occurrence_ids: &[String]) -> Result<()> {
let expected_schema = SchemaFingerprint::of(plan.caller_visible_output_schema());
let matching = self
.execution_scopes
.iter()
.filter(|shape| shape.matches(plan) && shape.output_schema_fingerprint() == expected_schema)
.collect::<Vec<_>>();
if matching.is_empty() {
return Err(QueryError::new(
QueryErrorCode::InternalInvariantViolation,
"query_engine.admission.evidence",
"the admitted capability evidence has no occurrence manifest for the native plan",
)
.with_fact("reason", "admitted_capability_scope_mismatch")
.with_fact("matching_shape_count", 0));
}
let scheduled = matching
.iter()
.map(|shape| {
shape.producer_occurrences().iter().map(|occurrence| occurrence.occurrence_id()).collect::<Vec<_>>()
})
.collect::<Vec<_>>();
if scheduled.iter().any(|candidate| candidate.as_slice() == occurrence_ids) {
return Ok(());
}
let Some(same_len) = scheduled.iter().find(|candidate| candidate.len() == occurrence_ids.len()) else {
return Err(QueryError::new(
QueryErrorCode::InternalInvariantViolation,
"query_engine.admission.evidence",
"the runtime composed input count differs from the admitted capability manifest",
)
.with_fact("schedule_reason", "runtime_occurrence_count_mismatch")
.with_fact("scheduled_occurrence_count", scheduled.first().map_or(0, Vec::len))
.with_fact("runtime_occurrence_count", occurrence_ids.len()));
};
for (scheduled, runtime) in same_len.iter().zip(occurrence_ids) {
if *scheduled != runtime {
return Err(QueryError::new(
QueryErrorCode::InternalInvariantViolation,
"query_engine.admission.evidence",
"the runtime composed input order differs from the admitted capability manifest",
)
.with_fact("schedule_reason", "runtime_occurrence_order_mismatch")
.with_fact("scheduled_occurrence_id", *scheduled)
.with_fact("runtime_occurrence_id", runtime));
}
}
Ok(())
}
#[doc(hidden)]
pub fn validate_covers_plan(&self, plan: &QueryPlan) -> Result<()> {
if plan.contains_graph_algorithm()
&& (!self.required_capabilities.contains(&CUGRAPH_GRAPH_EXECUTION_CAPABILITY)
|| !self.attested_cugraph_graph_execution_scopes.iter().any(|scope| scope.matches(plan)))
{
return Err(QueryError::new(
QueryErrorCode::InternalInvariantViolation,
"query_engine.admission.evidence",
"admitted capability evidence does not authorize cuGraph execution for the native plan",
)
.with_fact("reason", "admitted_capability_evidence_mismatch")
.with_fact("required_capability", CUGRAPH_GRAPH_EXECUTION_CAPABILITY.as_str())
.with_fact("admitted_capabilities", capability_labels(&self.required_capabilities)));
}
let execution_scope = plan.execution_fingerprint();
let scope_matches = self
.execution_scopes
.iter()
.filter(|scope| scope.matches_execution_scope_fingerprint(execution_scope))
.count();
let occurrence_matches = self
.execution_scopes
.iter()
.map(|scope| scope.producer_occurrence_scope_count(execution_scope))
.sum::<usize>();
let manifest_matches = self.execution_manifest.as_ref().and_then(|manifest| manifest.occurrence_for_plan(plan));
if scope_matches > 0 || occurrence_matches > 0 || manifest_matches.is_some() {
return Ok(());
}
Err(QueryError::new(
QueryErrorCode::InternalInvariantViolation,
"query_engine.admission.evidence",
"admitted capability evidence has no scope for the native plan about to execute",
)
.with_fact("reason", "admitted_capability_scope_mismatch")
.with_fact("plan_scope", execution_scope))
}
}
fn duplicate_execution_manifest_error() -> QueryError {
QueryError::new(
QueryErrorCode::InternalInvariantViolation,
"query_engine.admission.evidence",
"an admitted attempt has more than one execution manifest",
)
.with_fact("reason", "duplicate_execution_manifest")
}
pub fn capability_labels(capabilities: &[ExecutionCapability]) -> String {
capabilities.iter().map(|capability| capability.as_str()).collect::<Vec<_>>().join(",")
}