use std::sync::Arc;
use crate::LixError;
use crate::changelog::{ChangeId, CommitId};
use crate::common::{ExactValue, LixTimestamp};
use crate::row_pk::RowPk;
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct CommitGraphChange {
pub(crate) id: ChangeId,
pub(crate) account_id: String,
pub(crate) row_pk: RowPk,
pub(crate) schema_key: String,
pub(crate) file_id: Option<String>,
pub(crate) metadata: Option<lix_schema::Jsonb>,
pub(crate) snapshot: Option<Vec<u8>>,
pub(crate) created_at: LixTimestamp,
pub(crate) origin_key: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct CommitGraphNode {
pub(crate) is_checkpoint: bool,
pub(crate) commit_id: CommitId,
pub(crate) change_id: ChangeId,
pub(crate) account_id: String,
pub(crate) generation: u64,
pub(crate) parent_commit_ids: Vec<CommitId>,
pub(crate) base_commit_id: Option<CommitId>,
pub(crate) first_parent_jump_commit_id: CommitId,
pub(crate) first_parent_jump_span: u64,
pub(crate) created_at: LixTimestamp,
pub(crate) touched_scope_digest: crate::changelog::CommitTouchedScopeDigest,
}
impl ExactValue<CommitId> for CommitGraphNode {
fn matches_exact_key(&self, key: &CommitId) -> bool {
self.commit_id == *key
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct ReachableCommitGraphNode {
pub(crate) commit: CommitGraphNode,
pub(crate) depth: u32,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct CommitGraphEdge {
pub(crate) parent_commit_id: CommitId,
pub(crate) child_commit_id: CommitId,
pub(crate) parent_order: u32,
}
pub(crate) fn commit_edges(commits: &[CommitGraphNode]) -> Vec<CommitGraphEdge> {
commits
.iter()
.flat_map(|commit| {
commit
.parent_commit_ids
.iter()
.enumerate()
.map(|(parent_order, parent_commit_id)| CommitGraphEdge {
parent_commit_id: *parent_commit_id,
child_commit_id: commit.commit_id,
parent_order: parent_order as u32,
})
})
.collect()
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub(crate) struct CommitGraphChangeHistoryRequest {
pub(crate) row_pks: Vec<RowPk>,
pub(crate) schema_keys: Vec<String>,
pub(crate) file_ids: Vec<String>,
pub(crate) min_depth: Option<u32>,
pub(crate) max_depth: Option<u32>,
pub(crate) include_tombstones: bool,
pub(crate) limit: Option<usize>,
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct CommitGraphChangeHistoryEntry {
pub(crate) change: CommitGraphChange,
pub(crate) observed_commit_id: CommitId,
pub(crate) start_commit_id: CommitId,
pub(crate) depth: u32,
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct CommitGraphHistory {
pub(crate) entries: Vec<CommitGraphChangeHistoryEntry>,
pub(crate) reachable_nodes: Arc<[ReachableCommitGraphNode]>,
}
#[async_trait::async_trait]
pub(crate) trait CommitGraphReader: Send + Sync {
async fn load_node(
&mut self,
commit_id: &CommitId,
) -> Result<Option<CommitGraphNode>, LixError>;
async fn reachable_nodes(
&mut self,
head_commit_id: &CommitId,
) -> Result<Arc<[ReachableCommitGraphNode]>, LixError>;
async fn reachable_nodes_limited(
&mut self,
head_commit_id: &CommitId,
limit: usize,
) -> Result<Arc<[ReachableCommitGraphNode]>, LixError> {
let nodes = self.reachable_nodes(head_commit_id).await?;
Ok(nodes.iter().take(limit).cloned().collect())
}
async fn reachable_nodes_through_depth(
&mut self,
head_commit_id: &CommitId,
max_depth: u32,
) -> Result<Arc<[ReachableCommitGraphNode]>, LixError> {
let nodes = self.reachable_nodes(head_commit_id).await?;
Ok(nodes
.iter()
.take_while(|reachable| reachable.depth <= max_depth)
.cloned()
.collect())
}
}