mirror of
https://github.com/corda/corda.git
synced 2024-12-21 13:57:54 +00:00
Transaction notes now stored individually per row.
This commit is contained in:
commit
876b17bb12
@ -38,8 +38,7 @@ val DEFAULT_SESSION_ID = 0L
|
||||
* Active means they haven't been consumed yet (or we don't know about it).
|
||||
* Relevant means they contain at least one of our pubkeys.
|
||||
*/
|
||||
class Vault(val states: Iterable<StateAndRef<ContractState>>,
|
||||
val transactionNotes: Map<SecureHash, Set<String>> = emptyMap()) {
|
||||
class Vault(val states: Iterable<StateAndRef<ContractState>>) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
inline fun <reified T : ContractState> statesOfType() = states.filter { it.state.data is T } as List<StateAndRef<T>>
|
||||
|
||||
|
@ -18,6 +18,7 @@ import net.corda.core.utilities.loggerFor
|
||||
import net.corda.core.utilities.trace
|
||||
import net.corda.node.utilities.*
|
||||
import org.jetbrains.exposed.sql.ResultRow
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.statements.InsertStatement
|
||||
import rx.Observable
|
||||
import rx.subjects.PublishSubject
|
||||
@ -45,9 +46,13 @@ class NodeVaultService(private val services: ServiceHub) : SingletonSerializeAsT
|
||||
val stateRef = stateRef("transaction_id", "output_index")
|
||||
}
|
||||
|
||||
private data class TxnNote(val txnId: SecureHash, val note: String) {
|
||||
override fun toString() = "$txnId: $note"
|
||||
}
|
||||
|
||||
private object TransactionNotesTable : JDBCHashedTable("${NODE_DATABASE_PREFIX}vault_txn_notes") {
|
||||
val txnId = secureHash("txnId")
|
||||
val notes = text("notes")
|
||||
val txnId = secureHash("txnId").index()
|
||||
val note = text("note")
|
||||
}
|
||||
|
||||
private val mutex = ThreadBox(content = object {
|
||||
@ -60,21 +65,17 @@ class NodeVaultService(private val services: ServiceHub) : SingletonSerializeAsT
|
||||
}
|
||||
}
|
||||
|
||||
val transactionNotes = object : AbstractJDBCHashMap<SecureHash, Set<String>, TransactionNotesTable>(TransactionNotesTable, loadOnInit = false) {
|
||||
override fun keyFromRow(row: ResultRow): SecureHash {
|
||||
return row[table.txnId]
|
||||
val transactionNotes = object : AbstractJDBCHashSet<TxnNote, TransactionNotesTable>(TransactionNotesTable) {
|
||||
override fun elementFromRow(row: ResultRow): TxnNote = TxnNote(row[table.txnId], row[table.note])
|
||||
|
||||
override fun addElementToInsert(insert: InsertStatement, entry: TxnNote, finalizables: MutableList<() -> Unit>) {
|
||||
insert[table.txnId] = entry.txnId
|
||||
insert[table.note] = entry.note
|
||||
}
|
||||
|
||||
override fun valueFromRow(row: ResultRow): Set<String> {
|
||||
return row[table.notes].split(delimiters = ";").toSet()
|
||||
}
|
||||
|
||||
override fun addKeyToInsert(insert: InsertStatement, entry: Map.Entry<SecureHash, Set<String>>, finalizables: MutableList<() -> Unit>) {
|
||||
insert[table.txnId] = entry.key
|
||||
}
|
||||
|
||||
override fun addValueToInsert(insert: InsertStatement, entry: Map.Entry<SecureHash, Set<String>>, finalizables: MutableList<() -> Unit>) {
|
||||
insert[table.notes] = entry.value.joinToString(separator = ";")
|
||||
// TODO: caching (2nd tier db cache) and db results filtering (max records, date, other)
|
||||
fun select(txnId: SecureHash) : Iterable<String> {
|
||||
return table.select { table.txnId.eq(txnId) }.map { row -> row[table.note] }.toSet().asIterable()
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,14 +102,14 @@ class NodeVaultService(private val services: ServiceHub) : SingletonSerializeAsT
|
||||
}
|
||||
})
|
||||
|
||||
override val currentVault: Vault get() = mutex.locked { Vault(allUnconsumedStates(), transactionNotes) }
|
||||
override val currentVault: Vault get() = mutex.locked { Vault(allUnconsumedStates()) }
|
||||
|
||||
override val updates: Observable<Vault.Update>
|
||||
get() = mutex.locked { _updatesPublisher }
|
||||
|
||||
override fun track(): Pair<Vault, Observable<Vault.Update>> {
|
||||
return mutex.locked {
|
||||
Pair(Vault(allUnconsumedStates(), transactionNotes), _updatesPublisher.bufferUntilSubscribed())
|
||||
Pair(Vault(allUnconsumedStates()), _updatesPublisher.bufferUntilSubscribed())
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,16 +135,13 @@ class NodeVaultService(private val services: ServiceHub) : SingletonSerializeAsT
|
||||
|
||||
override fun addNoteToTransaction(txnId: SecureHash, noteText: String) {
|
||||
mutex.locked {
|
||||
val notes = transactionNotes.getOrPut(key = txnId, defaultValue = {
|
||||
setOf(noteText)
|
||||
})
|
||||
transactionNotes.put(txnId, notes.plus(noteText))
|
||||
transactionNotes.add(TxnNote(txnId, noteText))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getTransactionNotes(txnId: SecureHash): Iterable<String> {
|
||||
mutex.locked {
|
||||
return transactionNotes.get(txnId)!!.asIterable()
|
||||
return transactionNotes.select(txnId)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,6 +140,7 @@ class StrandLocalTransactionManager(initWithDatabase: Database) : TransactionMan
|
||||
// Composite columns for use with below Exposed helpers.
|
||||
data class PartyColumns(val name: Column<String>, val owningKey: Column<PublicKeyTree>)
|
||||
data class StateRefColumns(val txId: Column<SecureHash>, val index: Column<Int>)
|
||||
data class TxnNoteColumns(val txId: Column<SecureHash>, val note: Column<String>)
|
||||
|
||||
/**
|
||||
* [Table] column helpers for use with Exposed, as per [varchar] etc.
|
||||
@ -154,6 +155,7 @@ fun Table.localDate(name: String) = this.registerColumn<LocalDate>(name, LocalDa
|
||||
fun Table.localDateTime(name: String) = this.registerColumn<LocalDateTime>(name, LocalDateTimeColumnType)
|
||||
fun Table.instant(name: String) = this.registerColumn<Instant>(name, InstantColumnType)
|
||||
fun Table.stateRef(txIdColumnName: String, indexColumnName: String) = StateRefColumns(this.secureHash(txIdColumnName), this.integer(indexColumnName))
|
||||
fun Table.txnNote(txIdColumnName: String, txnNoteColumnName: String) = TxnNoteColumns(this.secureHash(txIdColumnName), this.text(txnNoteColumnName))
|
||||
|
||||
/**
|
||||
* [ColumnType] for marshalling to/from database on behalf of [PublicKey].
|
||||
|
@ -112,7 +112,7 @@ class NodeVaultServiceTest {
|
||||
services.vaultService.addNoteToTransaction(usefulTX.id, "USD Sample Note 1")
|
||||
services.vaultService.addNoteToTransaction(usefulTX.id, "USD Sample Note 2")
|
||||
services.vaultService.addNoteToTransaction(usefulTX.id, "USD Sample Note 3")
|
||||
assertEquals(1, services.vaultService.currentVault.transactionNotes.toList().size)
|
||||
val results = services.vaultService.getTransactionNotes(usefulTX.id)
|
||||
assertEquals(3, services.vaultService.getTransactionNotes(usefulTX.id).count())
|
||||
|
||||
// Issue more Money (GBP)
|
||||
@ -124,7 +124,6 @@ class NodeVaultServiceTest {
|
||||
services.recordTransactions(listOf(anotherTX))
|
||||
|
||||
services.vaultService.addNoteToTransaction(anotherTX.id, "GPB Sample Note 1")
|
||||
assertEquals(2, services.vaultService.currentVault.transactionNotes.toList().size)
|
||||
assertEquals(1, services.vaultService.getTransactionNotes(anotherTX.id).count())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user