Docs: Comprehensive inline rustdoc and architectural summary PDF

This commit is contained in:
anthonyrawlins
2026-03-03 18:05:53 +11:00
parent cc03616918
commit 0f28e4b669
2932 changed files with 14552 additions and 74 deletions

View File

@@ -1,26 +1,53 @@
//! chrs-graph library implementation using Dolt for graph persistence.
use chrono::Utc;
use serde_json::Value;
use std::{path::Path, process::Command};
use thiserror::Error;
use uuid::Uuid;
/// Enumeration of possible errors that can arise while interacting with the `DoltGraph`.
///
/// Each variant wraps an underlying error source, making it easier for callers to
/// understand the failure context and decide on remedial actions.
#[derive(Error, Debug)]
pub enum GraphError {
/// Propagates I/O errors from the standard library (e.g., filesystem access).
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
/// Represents a failure when executing a Dolt command.
#[error("Command failed: {0}")]
CommandFailed(String),
/// Propagates JSON (de)serialization errors from `serde_json`.
#[error("Serde JSON error: {0}")]
SerdeJson(#[from] serde_json::Error),
/// A generic catchall for errors that don't fit the other categories.
#[error("Other error: {0}")]
Other(String),
}
/// Wrapper around a Dolt repository that stores graph data.
///
/// The `DoltGraph` type encapsulates a path to a Dolt repo and provides highlevel
/// operations such as initializing the repo, committing changes, creating tables, and
/// inserting nodes expressed as JSON objects.
///
/// # Architectural Rationale
/// Dolt offers a Gitlike versioncontrolled SQL database, which aligns well with CHORUS's
/// need for an immutable, queryable history of graph mutations. By wrapping Dolt commands in
/// this struct we isolate the rest of the codebase from the commandline interface, making the
/// graph layer portable and easier to test.
pub struct DoltGraph {
/// Filesystem path to the root of the Dolt repository.
pub repo_path: std::path::PathBuf,
}
impl DoltGraph {
/// Initialise (or open) a Dolt repository at the given `path`.
///
/// If the directory does not already contain a `.dolt` subdirectory, the function runs
/// `dolt init` to create a new repository. Errors from the underlying command are wrapped in
/// `GraphError::CommandFailed`.
pub fn init(path: &Path) -> Result<Self, GraphError> {
if !path.join(".dolt").exists() {
let status = Command::new("dolt")
@@ -39,6 +66,11 @@ impl DoltGraph {
})
}
/// Execute a Dolt command with the specified arguments.
///
/// This helper centralises command execution and error handling. It runs `dolt` with the
/// provided argument slice, captures stdout/stderr, and returns `GraphError::CommandFailed`
/// when the command exits with a nonzero status.
fn run_cmd(&self, args: &[&str]) -> Result<(), GraphError> {
let output = Command::new("dolt")
.args(args)
@@ -51,16 +83,25 @@ impl DoltGraph {
Ok(())
}
/// Stage all changes and commit them with the provided `message`.
///
/// The method first runs `dolt add -A` to stage modifications, then `dolt commit -m`.
/// Any failure in these steps propagates as a `GraphError`.
pub fn commit(&self, message: &str) -> Result<(), GraphError> {
self.run_cmd(&["add", "-A"])?;
self.run_cmd(&["commit", "-m", message])?;
Ok(())
}
/// Create a SQL table within the Dolt repository.
///
/// `schema` should be a commaseparated column definition list (e.g., `"id INT PRIMARY KEY, name TEXT"`).
/// If the table already exists, the function treats it as a noop and returns `Ok(())`.
pub fn create_table(&self, table_name: &str, schema: &str) -> Result<(), GraphError> {
let query = format!("CREATE TABLE {} ({})", table_name, schema);
if let Err(e) = self.run_cmd(&["sql", "-q", &query]) {
if e.to_string().contains("already exists") {
// Table is already present not an error for our usecase.
return Ok(());
}
return Err(e);
@@ -69,6 +110,11 @@ impl DoltGraph {
Ok(())
}
/// Insert a node represented by a JSON object into the specified `table`.
///
/// The JSON `data` must be an object where keys correspond to column names. Supported value
/// types are strings, numbers, booleans, and null. Complex JSON structures are rejected because
/// they cannot be directly mapped to SQL scalar columns.
pub fn insert_node(&self, table: &str, data: Value) -> Result<(), GraphError> {
let obj = data
.as_object()
@@ -111,7 +157,11 @@ mod tests {
#[test]
fn test_init_create_table_and_commit() {
let dir = TempDir::new().unwrap();
// Initialise a Dolt repository in a temporary directory.
let graph = DoltGraph::init(dir.path()).expect("init failed");
graph.create_table("nodes", "id INT PRIMARY KEY, name TEXT").expect("create table failed");
// Create a simple `nodes` table.
graph
.create_table("nodes", "id INT PRIMARY KEY, name TEXT")
.expect("create table failed");
}
}