From 8e587772c2370a2df00bf9af62e3ce3dc07e49cd Mon Sep 17 00:00:00 2001 From: Nicolas Burtey Date: Tue, 22 Sep 2026 20:25:03 -0600 Subject: [PATCH] refactor(pagination)!: bump es-entity to 0.14.1, job to 0.16.1, obix to 0.13.1 Migrates to the es-entity 0.14 pagination API (Page enum, accessor methods for has_next_page/end_cursor, into_end_cursor) as adapted from #889, now against the published crates.io releases. - es-entity 0.13.0 -> 0.14.1 - job 0.15.2 -> 0.16.1 - obix 0.12.3 -> 0.13.1 (es-entity-macros + sqlparser 0.63 ride along) Part of the release-crate-chain roll: es-entity -> job -> obix -> cala -> lana-bank. --- Cargo.lock | 24 ++++---- Cargo.toml | 6 +- cala-ledger/src/entry/mod.rs | 11 ++-- cala-ledger/tests/account_set.rs | 6 +- cala-ledger/tests/balance.rs | 14 ++--- cala-ledger/tests/effective_balance.rs | 81 ++++++++++++-------------- cala-ledger/tests/entries_filter.rs | 23 +++++--- cala-ledger/tests/helpers.rs | 7 +++ fuzz/Cargo.lock | 24 ++++---- 9 files changed, 102 insertions(+), 94 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d9ebe90b..f80c6f4e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -867,9 +867,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "es-entity" -version = "0.13.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fb3c5aea95b26c71cca017d41e18401425306ebbe584266710cf5480d80db65" +checksum = "d763a47378d464e4d2b01d6c922a58171dfce77ff1bd88d178ebbb860c0dbc17" dependencies = [ "async-stream", "chrono", @@ -895,9 +895,9 @@ dependencies = [ [[package]] name = "es-entity-macros" -version = "0.13.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a928a22a5aff65307c4dabdc9cc2e87f3ac75bafe348467bbd4a500faadf4e" +checksum = "cd0cc572bebd395f88464e76ffcacb750fd8d48866f6455a0f85b33add2f4859" dependencies = [ "convert_case", "darling 0.24.0", @@ -1417,9 +1417,9 @@ checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "job" -version = "0.15.2" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5466e533e23142cb5ba79fc59b4acad91134cc23637842c77f93a72837b4400b" +checksum = "8c9d963b2769f32598a991afdc49c02e87da88cea4e9753ac6a954232c81002a" dependencies = [ "async-trait", "chrono", @@ -1623,9 +1623,9 @@ dependencies = [ [[package]] name = "obix" -version = "0.12.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f757a32e2ba5c3cbe5e8440b17d8ff16c209026ce4b2135c9515003f906935" +checksum = "d84094d6184a52b61c1dfada49942f5c9951565df2c39c7107ebdc95a74d7df8" dependencies = [ "async-trait", "chrono", @@ -1646,9 +1646,9 @@ dependencies = [ [[package]] name = "obix-macros" -version = "0.12.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f380213c9dcaac015773501f53de82af6e21853646739794877e71d2f4412312" +checksum = "4e3e8d16379a89b1c943d1e5fe450f294e7b176f69cbefac45ddfd0e73333e1b" dependencies = [ "darling 0.24.0", "proc-macro2", @@ -2474,9 +2474,9 @@ dependencies = [ [[package]] name = "sqlparser" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c6d1b651dc4edf07eead2a0c6c78016ce971bc2c10da5266861b13f25e7cec" +checksum = "3679862809bd1f92e563cf6fd820e28f39135303668001c10331d5027183e8b4" dependencies = [ "log", ] diff --git a/Cargo.toml b/Cargo.toml index e5589543..7c978a93 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,9 +15,9 @@ cala-types = { path = "cala-ledger-core-types", package = "cala-ledger-core-type cala-ledger = { path = "cala-ledger", version = "0.30.3-dev" } cel = "0.14.5" -es-entity = "0.13.0" -job = { version = "0.15.2", features = ["es-entity"] } -obix = { version = "0.12.3", default-features = false } +es-entity = "0.14.1" +job = { version = "0.16.1", features = ["es-entity"] } +obix = { version = "0.13.1", default-features = false } anyhow = "1.0.99" cached = { version = "4.0", features = ["async"] } diff --git a/cala-ledger/src/entry/mod.rs b/cala-ledger/src/entry/mod.rs index e4a9da5f..f4f12a1e 100644 --- a/cala-ledger/src/entry/mod.rs +++ b/cala-ledger/src/entry/mod.rs @@ -126,16 +126,19 @@ impl Entries { &self, transaction_id: TransactionId, ) -> Result, EntryError> { - let mut entries = self + let page = self .repo .list_for_transaction_id_by_created_at( transaction_id, Default::default(), Default::default(), ) - .await? - .into_parts() - .0; + .await?; + let mut entries = match page.into_page() { + es_entity::Page::Last { entities } | es_entity::Page::HasNext { entities, next: _ } => { + entities + } + }; entries.sort_by(|a, b| { let a_sequence = a.values().sequence; let b_sequence = b.values().sequence; diff --git a/cala-ledger/tests/account_set.rs b/cala-ledger/tests/account_set.rs index f4fb0a49..9d0be1aa 100644 --- a/cala-ledger/tests/account_set.rs +++ b/cala-ledger/tests/account_set.rs @@ -1502,7 +1502,7 @@ async fn members_pagination() -> anyhow::Result<()> { .await?; assert_eq!(ret.entities().len(), 2); - assert!(ret.has_next_page); + assert!(ret.has_next_page()); assert_eq!( ret.entities()[0].id.clone(), AccountSetMemberId::from(set_two.id()) @@ -1522,7 +1522,7 @@ async fn members_pagination() -> anyhow::Result<()> { .list_members_by_created_at(parent.id(), query_args) .await?; assert_eq!(ret.entities().len(), 2); - assert!(ret.has_next_page); + assert!(ret.has_next_page()); assert_eq!( ret.entities()[0].id.clone(), AccountSetMemberId::from(account_one.id()) @@ -1542,7 +1542,7 @@ async fn members_pagination() -> anyhow::Result<()> { .list_members_by_created_at(parent.id(), query_args) .await?; assert_eq!(ret.entities().len(), 1); - assert!(!ret.has_next_page); + assert!(!ret.has_next_page()); assert_eq!( ret.entities()[0].id.clone(), AccountSetMemberId::from(account_two.id()) diff --git a/cala-ledger/tests/balance.rs b/cala-ledger/tests/balance.rs index c7fdb019..291b8d01 100644 --- a/cala-ledger/tests/balance.rs +++ b/cala-ledger/tests/balance.rs @@ -25,30 +25,26 @@ fn assert_balance_amounts_sum( ); } -fn all_balances_query() -> es_entity::PaginatedQueryArgs { +fn all_balances_query() -> es_entity::PaginatedQueryArgs { es_entity::PaginatedQueryArgs { first: 100, after: None, } } -fn balances_by_currency( +fn balances_by_currency( balances: es_entity::PaginatedQueryRet, ) -> HashMap { - balances - .into_parts() - .0 + helpers::expect_single_page(balances) .into_iter() .map(|balance| (balance.details.currency, balance)) .collect() } -fn balances_by_id( +fn balances_by_id( balances: es_entity::PaginatedQueryRet, ) -> HashMap { - balances - .into_parts() - .0 + helpers::expect_single_page(balances) .into_iter() .map(|balance| { ( diff --git a/cala-ledger/tests/effective_balance.rs b/cala-ledger/tests/effective_balance.rs index d85fac82..2deef1bb 100644 --- a/cala-ledger/tests/effective_balance.rs +++ b/cala-ledger/tests/effective_balance.rs @@ -56,30 +56,26 @@ fn assert_balance_range_amounts_sum( assert_balance_amounts_sum(&actual.close, &first.close, &second.close); } -fn all_balances_query() -> es_entity::PaginatedQueryArgs { +fn all_balances_query() -> es_entity::PaginatedQueryArgs { es_entity::PaginatedQueryArgs { first: 100, after: None, } } -fn balances_by_currency( +fn balances_by_currency( balances: es_entity::PaginatedQueryRet, ) -> HashMap { - balances - .into_parts() - .0 + helpers::expect_single_page(balances) .into_iter() .map(|balance| (balance.details.currency, balance)) .collect() } -fn balances_by_id( +fn balances_by_id( balances: es_entity::PaginatedQueryRet, ) -> HashMap { - balances - .into_parts() - .0 + helpers::expect_single_page(balances) .into_iter() .map(|balance| { ( @@ -94,23 +90,19 @@ fn balances_by_id( .collect() } -fn ranges_by_currency( +fn ranges_by_currency( ranges: es_entity::PaginatedQueryRet, ) -> HashMap { - ranges - .into_parts() - .0 + helpers::expect_single_page(ranges) .into_iter() .map(|range| (range.close.details.currency, range)) .collect() } -fn ranges_by_id( +fn ranges_by_id( ranges: es_entity::PaginatedQueryRet, ) -> HashMap { - ranges - .into_parts() - .0 + helpers::expect_single_page(ranges) .into_iter() .map(|range| { ( @@ -1196,7 +1188,7 @@ async fn list_modified_since_basic() -> anyhow::Result<()> { .effective() .list_modified_since(journal.id(), since, all_balances_query()) .await?; - assert!(!page.has_next_page); + assert!(!page.has_next_page()); let tuples: HashSet<(AccountId, Currency, NaiveDate)> = page .entities() @@ -1293,13 +1285,12 @@ async fn list_modified_since_backdating_fanout() -> anyhow::Result<()> { .list_modified_since(journal.id(), since, all_balances_query()) .await?; - let recipient_btc: HashMap = page - .into_parts() - .0 - .into_iter() - .filter(|s| s.account_id == recipient_account.id() && s.currency == Currency::BTC) - .map(|s| (s.effective, s)) - .collect(); + let recipient_btc: HashMap = + helpers::expect_single_page(page) + .into_iter() + .filter(|s| s.account_id == recipient_account.id() && s.currency == Currency::BTC) + .map(|s| (s.effective, s)) + .collect(); assert_eq!( recipient_btc.keys().copied().collect::>(), @@ -1449,7 +1440,7 @@ async fn list_modified_since_pagination() -> anyhow::Result<()> { .effective() .list_modified_since(journal.id(), since, all_balances_query()) .await?; - assert!(!full.has_next_page); + assert!(!full.has_next_page()); assert_eq!(full.entities().len(), expected_count); let expected_tuples: HashSet<(AccountId, Currency, NaiveDate)> = full .entities() @@ -1461,25 +1452,29 @@ async fn list_modified_since_pagination() -> anyhow::Result<()> { // Page through with a small page size; the union must match exactly, // with no duplicates or gaps across cursor boundaries. let mut collected = Vec::new(); - let mut after = None; + let mut query = es_entity::PaginatedQueryArgs { + first: 3, + after: None, + }; let mut pages = 0; loop { let page = cala .balances() .effective() - .list_modified_since( - journal.id(), - since, - es_entity::PaginatedQueryArgs { first: 3, after }, - ) + .list_modified_since(journal.id(), since, query) .await?; pages += 1; - let (entities, next) = page.into_parts(); - assert!(entities.len() <= 3); - collected.extend(entities); - match next { - Some(query) => after = query.after, - None => break, + assert!(page.entities().len() <= 3); + match page.into_page() { + es_entity::Page::Last { entities } => { + collected.extend(entities); + break; + } + es_entity::Page::HasNext { entities, next } => { + collected.extend(entities); + assert_eq!(next.first, 3); + query = next.into(); + } } } assert!(pages > 1, "test setup should require multiple pages"); @@ -1508,7 +1503,7 @@ async fn list_modified_since_pagination() -> anyhow::Result<()> { ) .await?; assert_eq!(first_page.entities().len(), 1); - assert!(first_page.has_next_page); + assert!(first_page.has_next_page()); let boundary_tuple = ( first_page.entities()[0].account_id, first_page.entities()[0].currency, @@ -1523,11 +1518,11 @@ async fn list_modified_since_pagination() -> anyhow::Result<()> { since, es_entity::PaginatedQueryArgs { first: expected_count, - after: first_page.end_cursor, + after: first_page.into_end_cursor(), }, ) .await?; - assert!(!rest.has_next_page); + assert!(!rest.has_next_page()); assert_eq!(rest.entities().len(), expected_count - 1); assert!( rest.entities() @@ -1545,8 +1540,8 @@ async fn list_modified_since_pagination() -> anyhow::Result<()> { .list_modified_since(journal.id(), quiet_since, all_balances_query()) .await?; assert!(empty.entities().is_empty()); - assert!(!empty.has_next_page); - assert!(empty.end_cursor.is_none()); + assert!(!empty.has_next_page()); + assert!(empty.end_cursor().is_none()); Ok(()) } diff --git a/cala-ledger/tests/entries_filter.rs b/cala-ledger/tests/entries_filter.rs index 7f208a5c..91dbe1e3 100644 --- a/cala-ledger/tests/entries_filter.rs +++ b/cala-ledger/tests/entries_filter.rs @@ -93,7 +93,7 @@ async fn list_for_journal_id_filtered() -> anyhow::Result<()> { // No filter -> every entry in the journal, across both transactions. let all = page(&cala, journal.id(), EntriesFilter::default(), 100, None).await; assert_eq!(all.entities().len(), 12); - assert!(!all.has_next_page); + assert!(!all.has_next_page()); // effective == jan -> only the January transaction's entries. let only_jan = page( @@ -147,7 +147,7 @@ async fn list_for_journal_id_filtered() -> anyhow::Result<()> { ) .await; assert!(empty.entities().is_empty()); - assert!(empty.end_cursor.is_none()); + assert!(empty.end_cursor().is_none()); // created_at bounds derived from the entries themselves (avoids clock skew). let max_created = all.entities().iter().map(|e| e.created_at()).max().unwrap(); @@ -201,11 +201,18 @@ async fn list_for_journal_id_filtered() -> anyhow::Result<()> { }; let first_page = page(&cala, journal.id(), jun_filter(), 4, None).await; assert_eq!(first_page.entities().len(), 4); - assert!(first_page.has_next_page); + assert!(first_page.has_next_page()); - let second_page = page(&cala, journal.id(), jun_filter(), 4, first_page.end_cursor).await; + let second_page = page( + &cala, + journal.id(), + jun_filter(), + 4, + first_page.into_end_cursor(), + ) + .await; assert_eq!(second_page.entities().len(), 2); - assert!(!second_page.has_next_page); + assert!(!second_page.has_next_page()); // Ascending direction: oldest first, ordered on (created_at, id) -- entries // posted in the same transaction can share a created_at, so the id @@ -220,7 +227,7 @@ async fn list_for_journal_id_filtered() -> anyhow::Result<()> { ) .await; assert_eq!(asc_first.entities().len(), 5); - assert!(asc_first.has_next_page); + assert!(asc_first.has_next_page()); assert!(asc_first .entities() .windows(2) @@ -233,12 +240,12 @@ async fn list_for_journal_id_filtered() -> anyhow::Result<()> { journal.id(), EntriesFilter::default(), 100, - asc_first.end_cursor, + asc_first.into_end_cursor(), es_entity::ListDirection::Ascending, ) .await; assert_eq!(asc_rest.entities().len(), 7); - assert!(!asc_rest.has_next_page); + assert!(!asc_rest.has_next_page()); for entry in asc_rest.entities() { assert!(ids.insert(entry.id)); } diff --git a/cala-ledger/tests/helpers.rs b/cala-ledger/tests/helpers.rs index e9fa3664..09a29bdf 100644 --- a/cala-ledger/tests/helpers.rs +++ b/cala-ledger/tests/helpers.rs @@ -6,6 +6,13 @@ use cala_ledger::{ tx_template::*, AccountId, CalaLedger, Currency, }; +pub fn expect_single_page(page: es_entity::PaginatedQueryRet) -> Vec { + match page.into_page() { + es_entity::Page::Last { entities } => entities, + es_entity::Page::HasNext { .. } => panic!("expected all test results in one page"), + } +} + pub async fn init_pool() -> anyhow::Result { init_pool_with(sqlx::postgres::PgPoolOptions::new()).await } diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 0e78655c..74681e0f 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -741,9 +741,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "es-entity" -version = "0.13.1" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19321291ff5d9ce21ccb1c9d2023fe0b6fca71dd28467fff50776d18e8fb9e2e" +checksum = "d763a47378d464e4d2b01d6c922a58171dfce77ff1bd88d178ebbb860c0dbc17" dependencies = [ "async-stream", "chrono", @@ -768,9 +768,9 @@ dependencies = [ [[package]] name = "es-entity-macros" -version = "0.13.1" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51299af4c4e660282802aa91235f673d6ed79f5032d65c6786cb53aff738748" +checksum = "cd0cc572bebd395f88464e76ffcacb750fd8d48866f6455a0f85b33add2f4859" dependencies = [ "convert_case", "darling 0.24.0", @@ -1265,9 +1265,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "job" -version = "0.15.3" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "165584b25b7bb6fb21467498b8332812bc41185f29c377bbdc884d7bb9c162b2" +checksum = "8c9d963b2769f32598a991afdc49c02e87da88cea4e9753ac6a954232c81002a" dependencies = [ "async-trait", "chrono", @@ -1485,9 +1485,9 @@ dependencies = [ [[package]] name = "obix" -version = "0.12.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f757a32e2ba5c3cbe5e8440b17d8ff16c209026ce4b2135c9515003f906935" +checksum = "d84094d6184a52b61c1dfada49942f5c9951565df2c39c7107ebdc95a74d7df8" dependencies = [ "async-trait", "chrono", @@ -1508,9 +1508,9 @@ dependencies = [ [[package]] name = "obix-macros" -version = "0.12.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f380213c9dcaac015773501f53de82af6e21853646739794877e71d2f4412312" +checksum = "4e3e8d16379a89b1c943d1e5fe450f294e7b176f69cbefac45ddfd0e73333e1b" dependencies = [ "darling 0.24.0", "proc-macro2", @@ -2298,9 +2298,9 @@ dependencies = [ [[package]] name = "sqlparser" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c6d1b651dc4edf07eead2a0c6c78016ce971bc2c10da5266861b13f25e7cec" +checksum = "3679862809bd1f92e563cf6fd820e28f39135303668001c10331d5027183e8b4" dependencies = [ "log", ]