diff --git a/docs/source/api-vault-query.rst b/docs/source/api-vault-query.rst index 1adb4631b9..a44ab01aa9 100644 --- a/docs/source/api-vault-query.rst +++ b/docs/source/api-vault-query.rst @@ -259,13 +259,13 @@ Query for all states with pagination specification (10 results per page): .. note:: The result set metadata field `totalStatesAvailable` allows you to further paginate accordingly as demonstrated in the following example. -Query for all states using pagination specification and iterate using `totalStatesAvailable` field until no further +Query for all states using a pagination specification and iterate using the `totalStatesAvailable` field until no further pages available: -.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/events/ScheduledFlowTests.kt +.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt :language: kotlin - :start-after: DOCSTART VaultQueryExamplePaging - :end-before: DOCEND VaultQueryExamplePaging + :start-after: DOCSTART VaultQueryExample24 + :end-before: DOCEND VaultQueryExample24 :dedent: 8 **LinearState and DealState queries using** ``LinearStateQueryCriteria``: @@ -426,6 +426,14 @@ Query for consumed deal states or linear ids, specify a paging specification and :end-before: DOCEND VaultJavaQueryExample2 :dedent: 12 +Query for all states using a pagination specification and iterate using the `totalStatesAvailable` field until no further pages available: + +.. literalinclude:: ../../node/src/test/java/net/corda/node/services/vault/VaultQueryJavaTests.java + :language: java + :start-after: DOCSTART VaultQueryExample24 + :end-before: DOCEND VaultQueryExample24 + :dedent: 8 + **Aggregate Function queries using** ``VaultCustomQueryCriteria``: Aggregations on cash using various functions: @@ -465,8 +473,8 @@ identifier): .. literalinclude:: ../../node/src/test/java/net/corda/node/services/vault/VaultQueryJavaTests.java :language: java - :start-after: DOCSTART VaultJavaQueryExample4 - :end-before: DOCEND VaultJavaQueryExample4 + :start-after: DOCSTART VaultJavaQueryExample5 + :end-before: DOCEND VaultJavaQueryExample5 :dedent: 12 Troubleshooting diff --git a/node/src/test/java/net/corda/node/services/vault/VaultQueryJavaTests.java b/node/src/test/java/net/corda/node/services/vault/VaultQueryJavaTests.java index 7cd4ce468e..ca4b25c6a8 100644 --- a/node/src/test/java/net/corda/node/services/vault/VaultQueryJavaTests.java +++ b/node/src/test/java/net/corda/node/services/vault/VaultQueryJavaTests.java @@ -485,4 +485,46 @@ public class VaultQueryJavaTests { return tx; }); } + + private List> queryStatesWithPaging(VaultService vaultService, int pageSize) { + // DOCSTART VaultQueryExample24 + int pageNumber = DEFAULT_PAGE_NUM; + List> states = new ArrayList<>(); + long totalResults; + do { + PageSpecification pageSpec = new PageSpecification(pageNumber, pageSize); + Vault.Page results = vaultService.queryBy(Cash.State.class, new VaultQueryCriteria(), pageSpec); + totalResults = results.getTotalStatesAvailable(); + List> newStates = results.getStates(); + System.out.println(newStates.size()); + states.addAll(results.getStates()); + pageNumber++; + } while ((pageSize * (pageNumber - 1) <= totalResults)); + // DOCEND VaultQueryExample24 + return states; + } + + @Test + public void testExampleOfQueryingStatesWithPagingWorksCorrectly() { + Amount dollars100 = new Amount<>(100, Currency.getInstance("USD")); + database.transaction(tx -> { + vaultFiller.fillWithSomeTestCash(dollars100, issuerServices, 4, DUMMY_CASH_ISSUER); + return tx; + }); + database.transaction(tx -> { + assertThat(queryStatesWithPaging(vaultService, 5).size()).isEqualTo(4); + vaultFiller.fillWithSomeTestCash(dollars100, issuerServices, 1, DUMMY_CASH_ISSUER); + return tx; + }); + database.transaction(tx -> { + assertThat(queryStatesWithPaging(vaultService, 5).size()).isEqualTo(5); + vaultFiller.fillWithSomeTestCash(dollars100, issuerServices, 1, DUMMY_CASH_ISSUER); + return tx; + }); + + database.transaction(tx -> { + assertThat(queryStatesWithPaging(vaultService, 5).size()).isEqualTo(6); + return tx; + }); + } } diff --git a/node/src/test/kotlin/net/corda/node/services/events/ScheduledFlowTests.kt b/node/src/test/kotlin/net/corda/node/services/events/ScheduledFlowTests.kt index 5aea06bcfb..a878fb5a18 100644 --- a/node/src/test/kotlin/net/corda/node/services/events/ScheduledFlowTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/events/ScheduledFlowTests.kt @@ -11,8 +11,6 @@ import net.corda.core.flows.SchedulableFlow import net.corda.core.identity.Party import net.corda.core.node.services.VaultService import net.corda.core.node.services.queryBy -import net.corda.core.node.services.vault.DEFAULT_PAGE_NUM -import net.corda.core.node.services.vault.PageSpecification import net.corda.core.node.services.vault.QueryCriteria.VaultQueryCriteria import net.corda.core.node.services.vault.Sort import net.corda.core.node.services.vault.SortAttribute @@ -141,7 +139,7 @@ class ScheduledFlowTests { @Test fun `run a whole batch of scheduled flows`() { - val N = 100 + val N = 99 val futures = mutableListOf>() for (i in 0 until N) { futures.add(aliceNode.services.startFlow(InsertInitialStateFlow(bob, notary)).resultFuture) @@ -154,10 +152,10 @@ class ScheduledFlowTests { // Convert the states into maps to make error reporting easier val statesFromA: List> = aliceNode.database.transaction { - queryStatesWithPaging(aliceNode.services.vaultService) + queryStates(aliceNode.services.vaultService) } val statesFromB: List> = bobNode.database.transaction { - queryStatesWithPaging(bobNode.services.vaultService) + queryStates(bobNode.services.vaultService) } assertEquals("Expect all states to be present", 2 * N, statesFromA.count()) statesFromA.forEach { ref -> @@ -174,23 +172,6 @@ class ScheduledFlowTests { assertTrue("Expect all states have run the scheduled task", statesFromB.all { it.state.data.processed }) } - /** - * Query all states from the Vault, fetching results as a series of pages with ordered states in order to perform - * integration testing of that functionality. - * - * @return states ordered by the transaction ID. - */ - private fun queryStatesWithPaging(vaultService: VaultService): List> { - // DOCSTART VaultQueryExamplePaging - var pageNumber = DEFAULT_PAGE_NUM - val states = mutableListOf>() - do { - val pageSpec = PageSpecification(pageSize = PAGE_SIZE, pageNumber = pageNumber) - val results = vaultService.queryBy(VaultQueryCriteria(), pageSpec, SORTING) - states.addAll(results.states) - pageNumber++ - } while ((pageSpec.pageSize * (pageNumber)) <= results.totalStatesAvailable) - // DOCEND VaultQueryExamplePaging - return states.toList() - } + private fun queryStates(vaultService: VaultService): List> = + vaultService.queryBy(VaultQueryCriteria(), sorting = SORTING).states } diff --git a/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt b/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt index 92e33ab2e9..526b2ddda9 100644 --- a/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt @@ -1001,14 +1001,39 @@ class VaultQueryTests { } } + // example of querying states with paging using totalStatesAvailable + private fun queryStatesWithPaging(vaultService: VaultService, pageSize: Int): List> { + // DOCSTART VaultQueryExample24 + var pageNumber = DEFAULT_PAGE_NUM + val states = mutableListOf>() + do { + val pageSpec = PageSpecification(pageNumber = pageNumber, pageSize = pageSize) + val results = vaultService.queryBy(VaultQueryCriteria(), pageSpec) + states.addAll(results.states) + pageNumber++ + } while ((pageSpec.pageSize * (pageNumber - 1)) <= results.totalStatesAvailable) + // DOCEND VaultQueryExample24 + return states.toList() + } + + // test paging query example works + @Test + fun `test example of querying states with paging works correctly`() { + database.transaction { + vaultFiller.fillWithSomeTestCash(25.DOLLARS, notaryServices, 4, DUMMY_CASH_ISSUER) + assertThat(queryStatesWithPaging(vaultService, 5).count()).isEqualTo(4) + vaultFiller.fillWithSomeTestCash(25.DOLLARS, notaryServices, 1, DUMMY_CASH_ISSUER) + assertThat(queryStatesWithPaging(vaultService, 5).count()).isEqualTo(5) + vaultFiller.fillWithSomeTestCash(25.DOLLARS, notaryServices, 1, DUMMY_CASH_ISSUER) + assertThat(queryStatesWithPaging(vaultService, 5).count()).isEqualTo(6) + } + } + // sorting @Test fun `sorting - all states sorted by contract type, state status, consumed time`() { - setUpDb(database) - database.transaction { - val sortCol1 = Sort.SortColumn(SortAttribute.Standard(Sort.VaultStateAttribute.CONTRACT_STATE_TYPE), Sort.Direction.DESC) val sortCol2 = Sort.SortColumn(SortAttribute.Standard(Sort.VaultStateAttribute.STATE_STATUS), Sort.Direction.ASC) val sortCol3 = Sort.SortColumn(SortAttribute.Standard(Sort.VaultStateAttribute.CONSUMED_TIME), Sort.Direction.DESC)