sui_gql_client/queries/stream/
mod.rs

1//! Experimental abstractions to help create stream queries.
2//!
3//! Should be private until we iron out the api.
4use std::future::Future;
5
6use futures::Stream;
7
8use super::fragments::PageInfo;
9use crate::GraphQlClient;
10
11/// Helper for paginating queries forward.
12///
13/// # Arguments
14/// - `client`
15/// - `vars`: [`cynic::QueryVariables`] fragment; must implement [`UpdatePageInfo`]
16/// - `request`: async function that maps `(client, vars) -> Page<Iter>`, where `Iter` is an
17///   iterator over items of a **single** page's results
18pub(super) fn forward<'a, Client, Vars, Req, Fut, Iter, T, Err>(
19    client: &'a Client,
20    mut vars: Vars,
21    mut request: Req,
22) -> impl Stream<Item = Result<T, Err>> + 'a
23where
24    Client: GraphQlClient,
25    Vars: 'a + UpdatePageInfo + Clone,
26    Req: 'a + FnMut(&'a Client, Vars) -> Fut,
27    Fut: Future<Output = Result<Page<Iter>, Err>>,
28    Iter: IntoIterator<Item = Result<T, Err>>,
29    T: 'static,
30    Err: 'a,
31{
32    async_stream::try_stream! {
33        let mut has_next_page = true;
34        while has_next_page {
35            let page = request(client, vars.clone()).await?;
36
37            vars.update_page_info(&page.info);
38            has_next_page = page.info.has_next_page;
39
40            for value in page.data {
41                yield value?;
42            }
43        }
44    }
45}
46
47pub(super) struct Page<T> {
48    pub(super) info: PageInfo,
49    pub(super) data: T,
50}
51
52impl<T> Page<T> {
53    pub(super) fn new(page_info: impl Into<PageInfo>, data: T) -> Self {
54        Self {
55            info: page_info.into(),
56            data,
57        }
58    }
59}
60
61pub(super) trait UpdatePageInfo {
62    fn update_page_info(&mut self, info: &PageInfo);
63}