Ledger api server fixes to persist divulged, otherwise unknown contracts #2946 (#3101)

This commit is contained in:
Oliver Seeliger 2019-10-04 11:25:50 +02:00 committed by GitHub
parent 506da16650
commit 7dd482861b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 106 additions and 19 deletions

View File

@ -0,0 +1 @@
915fa54759b3e4f600a5413eaadd956823770a28bd6406e285bfe67968e5704a

View File

@ -0,0 +1,34 @@
-- Copyright (c) 2019 The DAML Authors. All rights reserved.
-- SPDX-License-Identifier: Apache-2.0
---------------------------------------------------------------------------------------------------
-- V4: Contract divulgence
--
-- This schema version builds on V1 and V3 by modifying the contract_divulgences.contract_id foreign key
-- to point to contract_data.id (rather than contracts.id previously). Because there is no way to alter a foreign key
-- constraint or to drop and add an unnamed constraint, the script rebuilds the contract_divulgences table.
ALTER TABLE contract_divulgences RENAME TO contract_divulgences_to_be_dropped;
ALTER TABLE contract_divulgences_to_be_dropped RENAME CONSTRAINT contract_divulgences_idx TO contract_divulgences_idx_to_be_dropped;
CREATE TABLE contract_divulgences (
contract_id varchar not null,
-- The party to which the given contract was divulged
party varchar not null,
-- The offset at which the contract was divulged to the given party
ledger_offset bigint not null,
-- The transaction ID at which the contract was divulged to the given party
transaction_id varchar not null,
foreign key (contract_id) references contract_data (id), -- refer to contract_data instead, the reason for this script
foreign key (ledger_offset) references ledger_entries (ledger_offset),
foreign key (transaction_id) references ledger_entries (transaction_id),
CONSTRAINT contract_divulgences_idx UNIQUE(contract_id, party)
);
INSERT INTO contract_divulgences (contract_id, party, ledger_offset, transaction_id)
SELECT contract_id, party, ledger_offset, transaction_id
FROM contract_divulgences_to_be_dropped;
DROP TABLE contract_divulgences_to_be_dropped;

View File

@ -0,0 +1 @@
486baf742542ad6b00e7f221b7419da374b64430afb10f6a89ad6bf3b43dccc6

View File

@ -0,0 +1,34 @@
-- Copyright (c) 2019 The DAML Authors. All rights reserved.
-- SPDX-License-Identifier: Apache-2.0
---------------------------------------------------------------------------------------------------
-- V9: Contract divulgence
--
-- This schema version builds on V2 and V8 by modifying the contract_divulgences.contract_id foreign key
-- to point to contract_data.id (rather than contracts.id previously). Because there is no way to alter a foreign key
-- constraint or to drop and add an unnamed constraint, the script rebuilds the contract_divulgences table.
ALTER TABLE contract_divulgences RENAME TO contract_divulgences_to_be_dropped;
ALTER TABLE contract_divulgences_to_be_dropped RENAME CONSTRAINT contract_divulgences_idx TO contract_divulgences_idx_to_be_dropped;
CREATE TABLE contract_divulgences (
contract_id varchar not null,
-- The party to which the given contract was divulged
party varchar not null,
-- The offset at which the contract was divulged to the given party
ledger_offset bigint not null,
-- The transaction ID at which the contract was divulged to the given party
transaction_id varchar not null,
foreign key (contract_id) references contract_data (id), -- refer to contract_data instead, the reason for this script
foreign key (ledger_offset) references ledger_entries (ledger_offset),
foreign key (transaction_id) references ledger_entries (transaction_id),
CONSTRAINT contract_divulgences_idx UNIQUE(contract_id, party)
);
INSERT INTO contract_divulgences (contract_id, party, ledger_offset, transaction_id)
SELECT contract_id, party, ledger_offset, transaction_id
FROM contract_divulgences_to_be_dropped;
DROP TABLE contract_divulgences_to_be_dropped;

View File

@ -194,15 +194,33 @@ private class JdbcLedgerDao(
"""insert into contracts(id, transaction_id, workflow_id, package_id, name, create_offset, key)
|values({id}, {transaction_id}, {workflow_id}, {package_id}, {name}, {create_offset}, {key})""".stripMargin
private val SQL_INSERT_CONTRACT_DATA =
"insert into contract_data(id, contract) values({id}, {contract})"
private val SQL_INSERT_CONTRACT_WITNESS =
"insert into contract_witnesses(contract_id, witness) values({contract_id}, {witness})"
private val SQL_INSERT_CONTRACT_KEY_MAINTAINERS =
"insert into contract_key_maintainers(contract_id, maintainer) values({contract_id}, {maintainer})"
private def storeContractData(contracts: Seq[(AbsoluteContractId, AbsoluteContractInst)])(
implicit connection: Connection): Unit = {
val namedContractDataParams = contracts
.map {
case (cid, contract) =>
Seq[NamedParameter](
"id" -> cid.coid,
"contract" -> contractSerializer
.serializeContractInstance(contract)
.getOrElse(sys.error(s"failed to serialize contract! cid:${cid.coid}"))
)
}
if (namedContractDataParams.nonEmpty) {
val _ = executeBatchSql(
queries.SQL_INSERT_CONTRACT_DATA,
namedContractDataParams
)
}
}
private def storeContracts(offset: Long, contracts: immutable.Seq[ActiveContract])(
implicit connection: Connection): Unit = {
@ -236,21 +254,7 @@ private class JdbcLedgerDao(
namedContractParams
)
val namedContractDataParams = contracts
.map(
c =>
Seq[NamedParameter](
"id" -> c.id.coid,
"contract" -> contractSerializer
.serializeContractInstance(c.contract)
.getOrElse(sys.error(s"failed to serialize contract! cid:${c.id.coid}"))
)
)
executeBatchSql(
SQL_INSERT_CONTRACT_DATA,
namedContractDataParams
)
storeContractData(contracts.map(c => (c.id, c.contract)))
// Part 2: insert witnesses into the 'contract_witnesses' table
val namedWitnessesParams = contracts
@ -561,6 +565,9 @@ private class JdbcLedgerDao(
Try {
storeTransaction(offset, tx)
// Ensure divulged contracts are known about before they are referred to.
storeContractData(divulgedContracts)
updateActiveContractSet(
offset,
tx,
@ -1262,6 +1269,7 @@ object JdbcLedgerDao {
sealed trait Queries {
// SQL statements using the proprietary Postgres on conflict .. do nothing clause
protected[JdbcLedgerDao] def SQL_INSERT_CONTRACT_DATA: String
protected[JdbcLedgerDao] def SQL_INSERT_PACKAGE: String
protected[JdbcLedgerDao] def SQL_IMPLICITLY_INSERT_PARTIES: String
@ -1279,6 +1287,10 @@ object JdbcLedgerDao {
object PostgresQueries extends Queries {
override protected[JdbcLedgerDao] val SQL_INSERT_CONTRACT_DATA: String =
"""insert into contract_data(id, contract) values({id}, {contract})
|on conflict (id) do nothing""".stripMargin
override protected[JdbcLedgerDao] val SQL_INSERT_PACKAGE: String =
"""insert into packages(package_id, upload_id, source_description, size, known_since, ledger_offset, package)
|select {package_id}, {upload_id}, {source_description}, {size}, {known_since}, ledger_end, {package}
@ -1307,6 +1319,10 @@ object JdbcLedgerDao {
object H2DatabaseQueries extends Queries {
override protected[JdbcLedgerDao] val SQL_INSERT_CONTRACT_DATA: String =
"""merge into contract_data using dual on id = {id}
|when not matched then insert (id, contract) values ({id}, {contract})""".stripMargin
override protected[JdbcLedgerDao] val SQL_INSERT_PACKAGE: String =
"""merge into packages using dual on package_id = {package_id}
|when not matched then insert (package_id, upload_id, source_description, size, known_since, ledger_offset, package)

View File

@ -38,6 +38,7 @@ HEAD — ongoing
even if they were present during parallel compilations.
- [Ledger] Enhance logging to correlate log messages with the associated participant id in multi-participant node tests and environments
- [Ledger] Ledger api server indexer closes akka system on shutdown.
- [Ledger] The ledger api server now stores divulged, otherwise unknown contracts.
- [DAML Studio] Fix a bug where the same module was imported twice
under different file paths breaking causing module name
collisions. See `issue #3099 <https://github.com/digital-asset/daml/issues/3099>`_.
collisions. See `issue #3099 <https://github.com/digital-asset/daml/issues/3099>`_.