lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README | LICENSE

commit 2b34514651a66fb7837aac2ad37d49c8eb59757b
parent ecd53f39ab8f8cc01de3cadfb0027b29b6038c3a
Author: triesap <tyson@radroots.org>
Date:   Mon, 15 Jun 2026 17:12:23 -0700

trade: expose order projection query metadata

- Add a query result wrapper carrying order projection, exact event count, applied limit, and typed event IDs.
- Keep projection reduction delegated to the existing reducer and event-store filtering path.
- Preserve the existing projection helper by deriving it from the richer query result.
- Cover the query metadata with event-store backed order projection tests.

Diffstat:
Mcrates/trade/src/order.rs | 50++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 48 insertions(+), 2 deletions(-)

diff --git a/crates/trade/src/order.rs b/crates/trade/src/order.rs @@ -379,6 +379,15 @@ pub enum RadrootsOrderStoreQueryError { } #[cfg(feature = "event_store")] +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct RadrootsOrderProjectionQueryResult { + pub projection: RadrootsOrderProjection, + pub event_count: usize, + pub limit_applied: u32, + pub event_ids: Vec<RadrootsEventId>, +} + +#[cfg(feature = "event_store")] pub async fn order_events_for_order_id( store: &RadrootsEventStore, order_id: &RadrootsOrderId, @@ -409,8 +418,29 @@ pub async fn order_projection_for_order_id( order_id: &RadrootsOrderId, limit: u32, ) -> Result<RadrootsOrderProjection, RadrootsOrderStoreQueryError> { + order_projection_query_for_order_id(store, order_id, limit) + .await + .map(|result| result.projection) +} + +#[cfg(feature = "event_store")] +pub async fn order_projection_query_for_order_id( + store: &RadrootsEventStore, + order_id: &RadrootsOrderId, + limit: u32, +) -> Result<RadrootsOrderProjectionQueryResult, RadrootsOrderStoreQueryError> { let records = order_events_for_order_id(store, order_id, limit).await?; - Ok(reduce_order_event_records(order_id, records)) + let event_ids = records + .iter() + .map(|record| record.event_id().clone()) + .collect::<Vec<_>>(); + let event_count = records.len(); + Ok(RadrootsOrderProjectionQueryResult { + projection: reduce_order_event_records(order_id, records), + event_count, + limit_applied: limit, + event_ids, + }) } #[cfg(feature = "event_store")] @@ -3953,7 +3983,7 @@ mod tests { #[cfg(feature = "event_store")] use super::{ ORDER_EVENT_CONTRACT_IDS, RadrootsOrderStoreQueryError, order_events_for_order_id, - order_projection_for_order_id, + order_projection_for_order_id, order_projection_query_for_order_id, }; use super::{ RadrootsListingInventoryAccountingInputs, RadrootsListingInventoryAccountingIssue, @@ -5042,6 +5072,22 @@ mod tests { Some(decision_event.id.as_str()) ); assert!(projection.issues.is_empty()); + + let result = order_projection_query_for_order_id(&store, &order_id("order-1"), 10) + .await + .expect("projection result"); + + assert_eq!(result.event_count, 2); + assert_eq!(result.limit_applied, 10); + assert_eq!( + result + .event_ids + .iter() + .map(RadrootsEventId::as_str) + .collect::<Vec<_>>(), + vec![request_event_id.as_str(), decision_event.id.as_str()] + ); + assert_eq!(result.projection.status, RadrootsOrderStatus::Accepted); } #[cfg(feature = "event_store")]