mirror of
https://github.com/corda/corda.git
synced 2024-12-25 07:31:10 +00:00
Automatically persist Linear and/or FungibleState attributes for quer… (#920)
* Automatically persist Linear and/or FungibleState attributes for querying (even when Contract does not implement QueryableState). * Return single() state.
This commit is contained in:
parent
f827db72da
commit
526007a085
@ -2,11 +2,14 @@ package net.corda.docs
|
|||||||
|
|
||||||
import net.corda.core.contracts.LinearState
|
import net.corda.core.contracts.LinearState
|
||||||
import net.corda.core.contracts.StateAndRef
|
import net.corda.core.contracts.StateAndRef
|
||||||
import net.corda.core.contracts.StateRef
|
import net.corda.core.contracts.UniqueIdentifier
|
||||||
import net.corda.core.getOrThrow
|
import net.corda.core.getOrThrow
|
||||||
import net.corda.core.node.ServiceHub
|
import net.corda.core.node.ServiceHub
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.node.services.linearHeadsOfType
|
import net.corda.core.node.services.Vault
|
||||||
|
import net.corda.core.node.services.queryBy
|
||||||
|
import net.corda.core.node.services.vault.QueryCriteria
|
||||||
|
import net.corda.core.node.services.vault.and
|
||||||
import net.corda.core.toFuture
|
import net.corda.core.toFuture
|
||||||
import net.corda.core.utilities.DUMMY_NOTARY
|
import net.corda.core.utilities.DUMMY_NOTARY
|
||||||
import net.corda.core.utilities.DUMMY_NOTARY_KEY
|
import net.corda.core.utilities.DUMMY_NOTARY_KEY
|
||||||
@ -26,10 +29,10 @@ class WorkflowTransactionBuildTutorialTest {
|
|||||||
lateinit var nodeB: MockNetwork.MockNode
|
lateinit var nodeB: MockNetwork.MockNode
|
||||||
|
|
||||||
// Helper method to locate the latest Vault version of a LinearState from a possibly out of date StateRef
|
// Helper method to locate the latest Vault version of a LinearState from a possibly out of date StateRef
|
||||||
private inline fun <reified T : LinearState> ServiceHub.latest(ref: StateRef): StateAndRef<T> {
|
private inline fun <reified T : LinearState> ServiceHub.latest(ref: UniqueIdentifier): StateAndRef<T> {
|
||||||
val linearHeads = vaultService.linearHeadsOfType<T>()
|
val linearHeads = vaultQueryService.queryBy<T>(QueryCriteria.LinearStateQueryCriteria(linearId = listOf(ref))
|
||||||
val original = storageService.validatedTransactions.getTransaction(ref.txhash)!!.tx.outRef<T>(ref.index)
|
.and(QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.UNCONSUMED)))
|
||||||
return linearHeads[original.state.data.linearId]!!
|
return linearHeads.states.single()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@ -59,14 +62,15 @@ class WorkflowTransactionBuildTutorialTest {
|
|||||||
val flow1 = nodeA.services.startFlow(SubmitTradeApprovalFlow("1234", nodeB.info.legalIdentity))
|
val flow1 = nodeA.services.startFlow(SubmitTradeApprovalFlow("1234", nodeB.info.legalIdentity))
|
||||||
// Wait for the flow to finish
|
// Wait for the flow to finish
|
||||||
val proposalRef = flow1.resultFuture.getOrThrow()
|
val proposalRef = flow1.resultFuture.getOrThrow()
|
||||||
|
val proposalLinearId = proposalRef.state.data.linearId
|
||||||
// Wait for NodeB to include it's copy in the vault
|
// Wait for NodeB to include it's copy in the vault
|
||||||
nodeBVaultUpdate.get()
|
nodeBVaultUpdate.get()
|
||||||
// Fetch the latest copy of the state from both nodes
|
// Fetch the latest copy of the state from both nodes
|
||||||
val latestFromA = nodeA.database.transaction {
|
val latestFromA = nodeA.database.transaction {
|
||||||
nodeA.services.latest<TradeApprovalContract.State>(proposalRef.ref)
|
nodeA.services.latest<TradeApprovalContract.State>(proposalLinearId)
|
||||||
}
|
}
|
||||||
val latestFromB = nodeB.database.transaction {
|
val latestFromB = nodeB.database.transaction {
|
||||||
nodeB.services.latest<TradeApprovalContract.State>(proposalRef.ref)
|
nodeB.services.latest<TradeApprovalContract.State>(proposalLinearId)
|
||||||
}
|
}
|
||||||
// Confirm the state as as expected
|
// Confirm the state as as expected
|
||||||
assertEquals(WorkflowState.NEW, proposalRef.state.data.state)
|
assertEquals(WorkflowState.NEW, proposalRef.state.data.state)
|
||||||
@ -87,10 +91,10 @@ class WorkflowTransactionBuildTutorialTest {
|
|||||||
secondNodeBVaultUpdate.get()
|
secondNodeBVaultUpdate.get()
|
||||||
// Fetch the latest copies from the vault
|
// Fetch the latest copies from the vault
|
||||||
val finalFromA = nodeA.database.transaction {
|
val finalFromA = nodeA.database.transaction {
|
||||||
nodeA.services.latest<TradeApprovalContract.State>(proposalRef.ref)
|
nodeA.services.latest<TradeApprovalContract.State>(proposalLinearId)
|
||||||
}
|
}
|
||||||
val finalFromB = nodeB.database.transaction {
|
val finalFromB = nodeB.database.transaction {
|
||||||
nodeB.services.latest<TradeApprovalContract.State>(proposalRef.ref)
|
nodeB.services.latest<TradeApprovalContract.State>(proposalLinearId)
|
||||||
}
|
}
|
||||||
// Confirm the state is as expected
|
// Confirm the state is as expected
|
||||||
assertEquals(WorkflowState.APPROVED, completedRef.state.data.state)
|
assertEquals(WorkflowState.APPROVED, completedRef.state.data.state)
|
||||||
|
@ -6,7 +6,6 @@ import net.corda.core.contracts.StateRef
|
|||||||
import net.corda.core.node.services.Vault
|
import net.corda.core.node.services.Vault
|
||||||
import net.corda.core.schemas.MappedSchema
|
import net.corda.core.schemas.MappedSchema
|
||||||
import net.corda.core.schemas.PersistentStateRef
|
import net.corda.core.schemas.PersistentStateRef
|
||||||
import net.corda.core.schemas.QueryableState
|
|
||||||
import net.corda.core.utilities.debug
|
import net.corda.core.utilities.debug
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.node.services.database.HibernateConfiguration
|
import net.corda.node.services.database.HibernateConfiguration
|
||||||
@ -34,13 +33,11 @@ class HibernateObserver(vaultUpdates: Observable<Vault.Update>, val config: Hibe
|
|||||||
|
|
||||||
private fun persistState(stateAndRef: StateAndRef<ContractState>) {
|
private fun persistState(stateAndRef: StateAndRef<ContractState>) {
|
||||||
val state = stateAndRef.state.data
|
val state = stateAndRef.state.data
|
||||||
if (state is QueryableState) {
|
logger.debug { "Asked to persist state ${stateAndRef.ref}" }
|
||||||
logger.debug { "Asked to persist state ${stateAndRef.ref}" }
|
config.schemaService.selectSchemas(state).forEach { persistStateWithSchema(state, stateAndRef.ref, it) }
|
||||||
config.schemaService.selectSchemas(state).forEach { persistStateWithSchema(state, stateAndRef.ref, it) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun persistStateWithSchema(state: QueryableState, stateRef: StateRef, schema: MappedSchema) {
|
fun persistStateWithSchema(state: ContractState, stateRef: StateRef, schema: MappedSchema) {
|
||||||
val sessionFactory = config.sessionFactoryForSchema(schema)
|
val sessionFactory = config.sessionFactoryForSchema(schema)
|
||||||
val session = sessionFactory.withOptions().
|
val session = sessionFactory.withOptions().
|
||||||
connection(TransactionManager.current().connection).
|
connection(TransactionManager.current().connection).
|
||||||
|
Loading…
Reference in New Issue
Block a user