use std::borrow::Cow;
use std::sync::Arc;
use anyhow::Result;
use crate::memory::config::MemoryConfig;
use crate::memory::score::extract::CompositeExtractor;
use crate::memory::tree::bucket_seal::{append_leaf, LabelStrategy, LeafRef};
use crate::memory::tree::flush::force_flush_tree;
use crate::memory::tree::registry::get_or_create_tree;
use crate::memory::tree::store::{archive_tree, Tree, TreeKind};
use crate::memory::tree::summarise::Summariser;
pub const GLOBAL_SCOPE: &str = "global";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TreeProfile {
Source,
Topic,
Global,
}
#[derive(Debug, Clone)]
pub struct TreeFactory<'a> {
profile: TreeProfile,
scope: Cow<'a, str>,
}
impl<'a> TreeFactory<'a> {
pub fn source(scope: impl Into<Cow<'a, str>>) -> Self {
Self {
profile: TreeProfile::Source,
scope: scope.into(),
}
}
pub fn topic(scope: impl Into<Cow<'a, str>>) -> Self {
Self {
profile: TreeProfile::Topic,
scope: scope.into(),
}
}
pub fn global() -> Self {
Self {
profile: TreeProfile::Global,
scope: Cow::Borrowed(GLOBAL_SCOPE),
}
}
pub fn from_tree(tree: &'a Tree) -> Self {
match tree.kind {
TreeKind::Source => Self::source(tree.scope.as_str()),
TreeKind::Topic => Self::topic(tree.scope.as_str()),
TreeKind::Global => Self::global(),
}
}
pub fn profile(&self) -> TreeProfile {
self.profile
}
pub fn kind(&self) -> TreeKind {
match self.profile {
TreeProfile::Source => TreeKind::Source,
TreeProfile::Topic => TreeKind::Topic,
TreeProfile::Global => TreeKind::Global,
}
}
pub fn scope(&self) -> &str {
self.scope.as_ref()
}
pub fn label_strategy(&self) -> LabelStrategy {
match self.kind() {
TreeKind::Source => {
LabelStrategy::ExtractFromContent(Arc::new(CompositeExtractor::regex_only()))
}
TreeKind::Topic | TreeKind::Global => LabelStrategy::Empty,
}
}
pub fn get_or_create(&self, config: &MemoryConfig) -> Result<Tree> {
get_or_create_tree(config, self.kind(), self.scope())
}
pub async fn insert_leaf(
&self,
config: &MemoryConfig,
leaf: &LeafRef,
summariser: &dyn Summariser,
) -> Result<Vec<String>> {
let tree = self.get_or_create(config)?;
let strategy = self.label_strategy();
append_leaf(config, &tree, leaf, summariser, &strategy).await
}
pub async fn seal_now(
&self,
config: &MemoryConfig,
summariser: &dyn Summariser,
) -> Result<Vec<String>> {
let tree = self.get_or_create(config)?;
let strategy = self.label_strategy();
force_flush_tree(config, &tree.id, None, summariser, &strategy).await
}
pub fn archive(&self, config: &MemoryConfig) -> Result<()> {
let tree = self.get_or_create(config)?;
archive_tree(config, &tree.id)
}
}
#[cfg(test)]
#[path = "factory_tests.rs"]
mod tests;