Skip to main content

Stream Query

A stream query allows querying events from the event store. When using Disentegrate, you can write a stream query and submit it to the event store to retrieve events. Alternatively, if you define a state query by deriving StateQuery, the library will generate a stream query for you. This query selects events from the specified stream and utilizes annotated id fields.

For example:

#[derive(Debug, StateQuery, Clone, Serialize, Deserialize)]
#[state_query(CourseEvent)]
pub struct Course {
#[id]
course_id: CourseId,
name: String,
created: bool,
closed: bool,
}

Under the hood, the library generates a stream query that fetches all events from the CourseEvent stream, filtering only those with the course_id specified in an instance of the Course struct.

How does it work if the stream has more than one ID, and you specify only a subset?

If the events included in your stream have multiple IDs, filtering for only a subset of those IDs will result in the query retrieving all the events that match the specified IDs while ignoring the others. For instance, if we filter only for the course_id, but the event StudentSubscribed has the student_id, it will still be selected if the course_id matches the one specified in the query.

Multi State query

Disintegrate automatically implements StateQuery for a tuple of StateQuery. The stream query of the tuple comprises the union of all its queries: the library retrieves all the queried events and mutates the StateQuerys in the tuple based on the specified filters. This feature is particularly useful for reusing the same query for multiple Decisions by combining shared StateQuerys in complex queries.

#[derive(Default, StateQuery, Clone, Serialize, Deserialize)]
#[state_query(CartEvent)]
pub struct Cart {
#[id]
user_id: String,
items: HashSet<Item>,
applied_coupon: Option<String>,
}

impl Cart {
pub fn new(user_id: &str) -> Self {
Self {
user_id: user_id.into(),
..Default::default()
}
}
}

#[derive(Default, StateQuery, Clone, Serialize, Deserialize)]
#[state_query(CouponEvent)]
pub struct Coupon {
#[id]
coupon_id: String,
quantity: u32,
}

impl Coupon {
pub fn new(coupon_id: &str) -> Self {
Self {
coupon_id: coupon_id.to_string(),
..Default::default()
}
}
}

fn state_query(&self) -> Self::StateQuery {
// returns a MultiStateQuery wich is the union of the Cart and Coupon `StateQuery`s
(Cart::new(&self.user_id), Coupon::new(&self.coupon_id))
}