commit 14ce82ac35fc72faa19bfe621f8af2b091cd8547
parent c3a816e70ec033c7d485385fe59778ef93d39be4
Author: triesap <tyson@radroots.org>
Date: Sat, 6 Jun 2026 02:36:24 -0700
bench: add listing workload
Diffstat:
3 files changed, 139 insertions(+), 0 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -4045,7 +4045,10 @@ version = "0.1.0"
dependencies = [
"tangle_nips",
"tangle_protocol",
+ "tangle_store",
+ "tangle_store_surreal",
"tangle_test_support",
+ "tokio",
]
[[package]]
diff --git a/crates/tangle_bench/Cargo.toml b/crates/tangle_bench/Cargo.toml
@@ -10,7 +10,12 @@ description = "Deterministic benchmark and proof-gate harnesses for tangle"
[dependencies]
tangle_nips = { path = "../tangle_nips" }
tangle_protocol = { path = "../tangle_protocol" }
+tangle_store = { path = "../tangle_store" }
+tangle_store_surreal = { path = "../tangle_store_surreal" }
tangle_test_support = { path = "../tangle_test_support" }
+[dev-dependencies]
+tokio = { version = "1", features = ["macros", "rt"] }
+
[lints]
workspace = true
diff --git a/crates/tangle_bench/src/lib.rs b/crates/tangle_bench/src/lib.rs
@@ -1,6 +1,11 @@
#![forbid(unsafe_code)]
use tangle_protocol::Event;
+use tangle_store::{StoreEventOutcome, StoredEvent};
+use tangle_store_surreal::{
+ ListingCurrentOutcome, ListingProjectionQuery, SurrealConnectionConfig, SurrealStore,
+ base_migration_plan,
+};
use tangle_test_support::{FixtureKey, build_fixture_event_from_parts};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -54,6 +59,100 @@ impl BenchDataset {
}
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct ListingWorkloadReport {
+ pub attempted: u64,
+ pub inserted: u64,
+ pub projected: u64,
+ pub listing_rows: u64,
+}
+
+#[derive(Debug, Clone)]
+pub struct MaterializedListingWorkload {
+ store: SurrealStore,
+ report: ListingWorkloadReport,
+}
+
+impl MaterializedListingWorkload {
+ pub fn store(&self) -> &SurrealStore {
+ &self.store
+ }
+
+ pub fn report(&self) -> ListingWorkloadReport {
+ self.report
+ }
+}
+
+pub async fn materialize_listing_workload(
+ dataset: &BenchDataset,
+) -> Result<MaterializedListingWorkload, String> {
+ let store = bench_memory_store("listing_workload").await?;
+ let mut inserted = 0;
+ let mut projected = 0;
+ for event in dataset.listings() {
+ let now = event.unsigned().created_at();
+ if store
+ .store_raw_event(&StoredEvent::new(event.clone(), now))
+ .await
+ .map_err(|error| error.to_string())?
+ == StoreEventOutcome::Inserted
+ {
+ inserted += 1;
+ }
+ store
+ .index_event_tags(event)
+ .await
+ .map_err(|error| error.to_string())?;
+ store
+ .maintain_current_event(event)
+ .await
+ .map_err(|error| error.to_string())?;
+ store
+ .store_listing_revision(event, now)
+ .await
+ .map_err(|error| error.to_string())?;
+ if store
+ .project_current_listing(event, now)
+ .await
+ .map_err(|error| error.to_string())?
+ == ListingCurrentOutcome::Projected
+ {
+ projected += 1;
+ }
+ store
+ .project_listing_helpers(event)
+ .await
+ .map_err(|error| error.to_string())?;
+ }
+ let listing_rows = store
+ .query_current_listings(&ListingProjectionQuery::new().with_effective_status("active"))
+ .await
+ .map_err(|error| error.to_string())?
+ .len() as u64;
+ Ok(MaterializedListingWorkload {
+ store,
+ report: ListingWorkloadReport {
+ attempted: dataset.listings().len() as u64,
+ inserted,
+ projected,
+ listing_rows,
+ },
+ })
+}
+
+async fn bench_memory_store(database: &str) -> Result<SurrealStore, String> {
+ let config = SurrealConnectionConfig::memory("tangle_bench", database)
+ .map_err(|error| error.to_string())?;
+ let store = SurrealStore::connect_memory(&config)
+ .await
+ .map_err(|error| error.to_string())?;
+ store
+ .apply_plan(&base_migration_plan())
+ .await
+ .map_err(|error| error.to_string())?;
+ Ok(store)
+}
+
fn bench_listing(index: usize) -> Result<Event, String> {
let created_at = 1_714_200_000 + index as u64;
let price_major = 10 + (index % 50);
@@ -160,4 +259,36 @@ mod tests {
.all(|event| event.unsigned().kind().as_u32() == 1)
);
}
+
+ #[tokio::test]
+ async fn listing_workload_materializes_projected_listing_rows() {
+ let dataset = BenchDataset::generate(BenchDatasetConfig::new(8, 3)).expect("dataset");
+ let materialized = super::materialize_listing_workload(&dataset)
+ .await
+ .expect("listing workload");
+ let report = materialized.report();
+
+ assert_eq!(
+ report,
+ super::ListingWorkloadReport {
+ attempted: 8,
+ inserted: 8,
+ projected: 8,
+ listing_rows: 8
+ }
+ );
+ assert_eq!(
+ materialized
+ .store()
+ .query_current_listings(
+ &tangle_store_surreal::ListingProjectionQuery::new()
+ .with_effective_status("active")
+ .with_limit(3)
+ )
+ .await
+ .expect("listing rows")
+ .len(),
+ 3
+ );
+ }
}