use std::sync::Arc;
use diskann::{graph::DiskANNIndex, provider::DataProvider};
use diskann_benchmark_runner::utils::fmt::{Delimit, Quote};
use crate::{
backend::index::result::AggregatedSearchResults, inputs::graph_index::SearchPhaseKind,
};
pub(crate) trait Plugin<DP, Kind, Params>: std::fmt::Debug
where
DP: DataProvider,
{
fn is_match(&self, kind: &Kind) -> bool;
fn kind(&self) -> &'static str;
fn run(
&self,
index: Arc<DiskANNIndex<DP>>,
kind: &Kind,
parameters: &Params,
) -> anyhow::Result<AggregatedSearchResults>;
}
#[derive(Debug)]
pub(crate) struct Plugins<DP, Kind, Params>
where
DP: DataProvider,
{
plugins: Vec<Box<dyn Plugin<DP, Kind, Params>>>,
}
impl<DP, Kind, Params> Plugins<DP, Kind, Params>
where
DP: DataProvider,
{
pub(crate) fn new() -> Self {
Self {
plugins: Vec::new(),
}
}
pub(crate) fn register<T>(&mut self, plugin: T)
where
T: Plugin<DP, Kind, Params> + 'static,
{
self.plugins.push(Box::new(plugin));
}
pub(crate) fn kinds(
&self,
) -> impl ExactSizeIterator<Item = &'static str> + use<'_, DP, Kind, Params> {
self.plugins.iter().map(|p| p.kind())
}
pub(crate) fn is_match(&self, kind: &Kind) -> bool {
self.plugins.iter().any(|p| p.is_match(kind))
}
pub(crate) fn format_kinds(&self) -> impl std::fmt::Display + use<'_, DP, Kind, Params> {
Delimit::new(self.kinds().map(Quote), ", ")
.with_last(", and ")
.with_pair(" and ")
}
pub(crate) fn run(
&self,
index: Arc<DiskANNIndex<DP>>,
kind: &Kind,
parameters: &Params,
) -> anyhow::Result<AggregatedSearchResults>
where
Kind: std::fmt::Debug,
{
match self.plugins.iter().find(|p| p.is_match(kind)) {
Some(plugin) => plugin.run(index, kind, parameters),
None => Err(anyhow::anyhow!(
"INTERNAL ERROR: Could not find a suitable search plugin for {:?}",
kind
)),
}
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct Topk;
impl Topk {
pub(crate) fn kind() -> SearchPhaseKind {
SearchPhaseKind::Topk
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct Range;
impl Range {
pub(crate) fn kind() -> SearchPhaseKind {
SearchPhaseKind::Range
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct TopkBetaFilter;
impl TopkBetaFilter {
pub(crate) fn kind() -> SearchPhaseKind {
SearchPhaseKind::TopkBetaFilter
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct TopkMultihopFilter;
impl TopkMultihopFilter {
pub(crate) fn kind() -> SearchPhaseKind {
SearchPhaseKind::TopkMultihopFilter
}
}