tangle


git clone https://radroots.dev/git/tangle.git
Log | Files | Refs | README | LICENSE

commit 314bfb7ba718c3c309058304110c55cbb39965da
parent 93cd88dc6f6daa63e70705ea9da890996aea7b62
Author: triesap <tyson@radroots.org>
Date:   Sat, 13 Jun 2026 16:30:32 -0700

build: add chorus pocket startup scaffold

- switch Pocket dependencies to the triesap fork source
- add a Pocket store handle with Tangle group tables
- expose a Chorus/Pocket runtime startup probe
- record fork source pins and targeted validation

Diffstat:
MCargo.lock | 6++++--
Mcrates/tangle_runtime/Cargo.toml | 2++
Acrates/tangle_runtime/src/chorus_pocket.rs | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcrates/tangle_runtime/src/lib.rs | 2++
Mcrates/tangle_store_pocket/Cargo.toml | 4++--
Mcrates/tangle_store_pocket/src/lib.rs | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
6 files changed, 213 insertions(+), 9 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -2923,7 +2923,7 @@ checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "pocket-db" version = "0.1.0" -source = "git+https://github.com/mikedilger/pocket?rev=329334f20948c796c6016b673b92551ac4855ad7#329334f20948c796c6016b673b92551ac4855ad7" +source = "git+https://github.com/triesap/pocket?rev=329334f20948c796c6016b673b92551ac4855ad7#329334f20948c796c6016b673b92551ac4855ad7" dependencies = [ "heed", "libc", @@ -2934,7 +2934,7 @@ dependencies = [ [[package]] name = "pocket-types" version = "0.1.0" -source = "git+https://github.com/mikedilger/pocket?rev=329334f20948c796c6016b673b92551ac4855ad7#329334f20948c796c6016b673b92551ac4855ad7" +source = "git+https://github.com/triesap/pocket?rev=329334f20948c796c6016b673b92551ac4855ad7#329334f20948c796c6016b673b92551ac4855ad7" dependencies = [ "derive_more", "rand 0.9.4", @@ -4387,9 +4387,11 @@ dependencies = [ "serde_json", "sha2", "tangle_core", + "tangle_groups", "tangle_nips", "tangle_protocol", "tangle_store", + "tangle_store_pocket", "tangle_store_surreal", "tangle_test_support", "tokio", diff --git a/crates/tangle_runtime/Cargo.toml b/crates/tangle_runtime/Cargo.toml @@ -14,9 +14,11 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" sha2 = "0.10" tangle_core = { path = "../tangle_core" } +tangle_groups = { path = "../tangle_groups" } tangle_nips = { path = "../tangle_nips" } tangle_protocol = { path = "../tangle_protocol" } tangle_store = { path = "../tangle_store" } +tangle_store_pocket = { path = "../tangle_store_pocket" } tangle_store_surreal = { path = "../tangle_store_surreal" } tokio = { version = "1", features = ["net", "sync"] } tracing = "0.1" diff --git a/crates/tangle_runtime/src/chorus_pocket.rs b/crates/tangle_runtime/src/chorus_pocket.rs @@ -0,0 +1,109 @@ +use core::fmt; +use std::path::{Path, PathBuf}; +use tangle_groups::GroupRuntimeConfig; +use tangle_store_pocket::{PocketStoreConfig, PocketStoreError, PocketStoreHandle}; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ChorusPocketRuntimeConfig { + pocket: PocketStoreConfig, + groups: GroupRuntimeConfig, +} + +impl ChorusPocketRuntimeConfig { + pub fn new(pocket: PocketStoreConfig, groups: GroupRuntimeConfig) -> Self { + Self { pocket, groups } + } + + pub fn pocket(&self) -> &PocketStoreConfig { + &self.pocket + } + + pub fn groups(&self) -> &GroupRuntimeConfig { + &self.groups + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ChorusPocketStartupReport { + store_directory: PathBuf, + groups_enabled: bool, +} + +impl ChorusPocketStartupReport { + pub fn store_directory(&self) -> &Path { + &self.store_directory + } + + pub fn groups_enabled(&self) -> bool { + self.groups_enabled + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ChorusPocketRuntimeError { + message: String, +} + +impl ChorusPocketRuntimeError { + pub fn message(&self) -> &str { + &self.message + } +} + +impl fmt::Display for ChorusPocketRuntimeError { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str(&self.message) + } +} + +impl std::error::Error for ChorusPocketRuntimeError {} + +impl From<PocketStoreError> for ChorusPocketRuntimeError { + fn from(error: PocketStoreError) -> Self { + Self { + message: error.to_string(), + } + } +} + +pub fn probe_chorus_pocket_startup( + config: &ChorusPocketRuntimeConfig, +) -> Result<ChorusPocketStartupReport, ChorusPocketRuntimeError> { + let store = PocketStoreHandle::open(config.pocket())?; + store.sync()?; + Ok(ChorusPocketStartupReport { + store_directory: store.dir().to_path_buf(), + groups_enabled: config.groups().enabled(), + }) +} + +#[cfg(test)] +mod tests { + use super::{ChorusPocketRuntimeConfig, probe_chorus_pocket_startup}; + use tangle_groups::parse_group_runtime_config_json; + use tangle_store_pocket::{PocketStoreConfig, PocketSyncPolicy}; + + #[test] + fn chorus_pocket_startup_probe_opens_store_and_reports_group_state() { + let root = std::env::temp_dir().join(format!( + "tangle-chorus-pocket-runtime-{}", + std::process::id() + )); + let pocket = PocketStoreConfig::new( + root.join("pocket"), + 1024 * 1024 * 1024, + 128, + PocketSyncPolicy::FlushOnShutdown, + ) + .expect("pocket"); + let groups = parse_group_runtime_config_json(r#"{"enabled": false}"#).expect("groups"); + let config = ChorusPocketRuntimeConfig::new(pocket.clone(), groups); + + let report = probe_chorus_pocket_startup(&config).expect("startup"); + + assert_eq!(report.store_directory(), pocket.data_directory()); + assert!(!report.groups_enabled()); + + let _ = std::fs::remove_dir_all(root); + } +} diff --git a/crates/tangle_runtime/src/lib.rs b/crates/tangle_runtime/src/lib.rs @@ -1,5 +1,7 @@ #![forbid(unsafe_code)] +pub mod chorus_pocket; + use axum::{ Json, Router, extract::ws::{Message, WebSocket, WebSocketUpgrade}, diff --git a/crates/tangle_store_pocket/Cargo.toml b/crates/tangle_store_pocket/Cargo.toml @@ -8,8 +8,8 @@ license.workspace = true description = "Pocket storage boundary for tangle" [dependencies] -pocket-db = { git = "https://github.com/mikedilger/pocket", rev = "329334f20948c796c6016b673b92551ac4855ad7" } -pocket-types = { git = "https://github.com/mikedilger/pocket", rev = "329334f20948c796c6016b673b92551ac4855ad7" } +pocket-db = { git = "https://github.com/triesap/pocket", rev = "329334f20948c796c6016b673b92551ac4855ad7" } +pocket-types = { git = "https://github.com/triesap/pocket", rev = "329334f20948c796c6016b673b92551ac4855ad7" } [lints] workspace = true diff --git a/crates/tangle_store_pocket/src/lib.rs b/crates/tangle_store_pocket/src/lib.rs @@ -3,9 +3,12 @@ use core::fmt; use pocket_db::Store; use pocket_types::{Event, Filter, Id, Pubkey}; -use std::path::{Path, PathBuf}; +use std::{ + io, + path::{Path, PathBuf}, +}; -pub const POCKET_SOURCE_REPOSITORY: &str = "https://github.com/mikedilger/pocket"; +pub const POCKET_SOURCE_REPOSITORY: &str = "https://github.com/triesap/pocket"; pub const POCKET_SOURCE_REVISION: &str = "329334f20948c796c6016b673b92551ac4855ad7"; pub type PocketEvent = Event; @@ -14,6 +17,9 @@ pub type PocketFilter = Filter; pub type PocketPubkey = Pubkey; pub type PocketStore = Store; +pub const TANGLE_POCKET_EXTRA_TABLES: [&str; 3] = + ["group_projection", "group_outbox", "group_checkpoint"]; + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct PocketDependencyBoundary { source_repository: &'static str, @@ -37,6 +43,32 @@ impl PocketDependencyBoundary { } } +pub struct PocketStoreHandle { + store: PocketStore, +} + +impl PocketStoreHandle { + pub fn open(config: &PocketStoreConfig) -> Result<Self, PocketStoreError> { + std::fs::create_dir_all(config.data_directory()) + .map_err(|error| PocketStoreError::from_create_dir(config.data_directory(), error))?; + let store = PocketStore::new(config.data_directory(), TANGLE_POCKET_EXTRA_TABLES.to_vec()) + .map_err(PocketStoreError::from_pocket)?; + Ok(Self { store }) + } + + pub fn dir(&self) -> &Path { + self.store.dir() + } + + pub fn sync(&self) -> Result<(), PocketStoreError> { + self.store.sync().map_err(PocketStoreError::from_pocket) + } + + pub fn into_inner(self) -> PocketStore { + self.store + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum PocketSyncPolicy { FlushOnWrite, @@ -129,20 +161,54 @@ impl fmt::Display for PocketConfigError { impl std::error::Error for PocketConfigError {} +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct PocketStoreError { + message: String, +} + +impl PocketStoreError { + pub fn from_create_dir(path: &Path, error: io::Error) -> Self { + Self { + message: format!( + "failed to create Pocket store directory {}: {error}", + path.display() + ), + } + } + + pub fn from_pocket(error: pocket_db::Error) -> Self { + Self { + message: error.to_string(), + } + } + + pub fn message(&self) -> &str { + &self.message + } +} + +impl fmt::Display for PocketStoreError { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str(&self.message) + } +} + +impl std::error::Error for PocketStoreError {} + #[cfg(test)] mod tests { use super::{ POCKET_SOURCE_REPOSITORY, POCKET_SOURCE_REVISION, PocketDependencyBoundary, - PocketStoreConfig, PocketSyncPolicy, + PocketStoreConfig, PocketStoreHandle, PocketSyncPolicy, TANGLE_POCKET_EXTRA_TABLES, }; #[test] - fn pocket_dependency_boundary_pins_chorus_latest_manifest_revision() { + fn pocket_dependency_boundary_pins_triesap_revision() { let boundary = PocketDependencyBoundary::current(); assert_eq!( boundary.source_repository(), - "https://github.com/mikedilger/pocket" + "https://github.com/triesap/pocket" ); assert_eq!(boundary.source_repository(), POCKET_SOURCE_REPOSITORY); assert_eq!( @@ -153,6 +219,29 @@ mod tests { } #[test] + fn pocket_store_handle_opens_syncs_and_exposes_tangle_tables() { + let root = std::env::temp_dir().join(format!("tangle-pocket-store-{}", std::process::id())); + let config = PocketStoreConfig::new( + root.join("pocket"), + 1024 * 1024 * 1024, + 128, + PocketSyncPolicy::FlushOnShutdown, + ) + .expect("config"); + + let handle = PocketStoreHandle::open(&config).expect("open"); + + assert_eq!(handle.dir(), config.data_directory()); + assert_eq!( + TANGLE_POCKET_EXTRA_TABLES, + ["group_projection", "group_outbox", "group_checkpoint"] + ); + handle.sync().expect("sync"); + + let _ = std::fs::remove_dir_all(root); + } + + #[test] fn pocket_store_config_preserves_explicit_storage_boundary() { let config = PocketStoreConfig::new( "runtime/radroots/tangle/pocket",