Docs: Comprehensive inline rustdoc and architectural summary PDF
This commit is contained in:
@@ -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 catch‑all 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 high‑level
|
||||
/// operations such as initializing the repo, committing changes, creating tables, and
|
||||
/// inserting nodes expressed as JSON objects.
|
||||
///
|
||||
/// # Architectural Rationale
|
||||
/// Dolt offers a Git‑like version‑controlled SQL database, which aligns well with CHORUS's
|
||||
/// need for an immutable, query‑able history of graph mutations. By wrapping Dolt commands in
|
||||
/// this struct we isolate the rest of the codebase from the command‑line 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` sub‑directory, 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 non‑zero 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 comma‑separated column definition list (e.g., `"id INT PRIMARY KEY, name TEXT"`).
|
||||
/// If the table already exists, the function treats it as a no‑op 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 use‑case.
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user