Skip to content

Commit eff24a6

Browse files
committed
Move listSortedRewardCoupons to common code DbTransferInputQueries
Extracted duplicated listSortedRewardCoupons method from DbUserWalletStore and DbExternalPartyWalletStore into a new shared mixin trait. PR reviewed in #3646 Signed-off-by: Divam <dfordivam@gmail.com>
1 parent 45cd83e commit eff24a6

File tree

3 files changed

+106
-113
lines changed

3 files changed

+106
-113
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package org.lfdecentralizedtrust.splice.store.db
5+
6+
import com.daml.ledger.javaapi.data.codegen.ContractId
7+
import org.lfdecentralizedtrust.splice.codegen.java.splice.round.IssuingMiningRound
8+
import org.lfdecentralizedtrust.splice.codegen.java.splice.types.Round
9+
import org.lfdecentralizedtrust.splice.store.MultiDomainAcsStore.ContractCompanion
10+
import org.lfdecentralizedtrust.splice.store.db.AcsQueries.{AcsStoreId, SelectFromAcsTableResult}
11+
import org.lfdecentralizedtrust.splice.store.{Limit, LimitHelpers, TransferInputStore}
12+
import org.lfdecentralizedtrust.splice.util.{Contract, TemplateJsonDecoder}
13+
import org.lfdecentralizedtrust.splice.util.FutureUnlessShutdownUtil.futureUnlessShutdownToFuture
14+
import com.digitalasset.canton.lifecycle.CloseContext
15+
import com.digitalasset.canton.resource.DbStorage
16+
import com.digitalasset.canton.resource.DbStorage.Implicits.BuilderChain.*
17+
import com.digitalasset.canton.tracing.TraceContext
18+
import slick.jdbc.canton.ActionBasedSQLInterpolation.Implicits.actionBasedSQLInterpolationCanton
19+
import slick.jdbc.canton.SQLActionBuilder
20+
21+
import scala.concurrent.{ExecutionContext, Future}
22+
23+
/** TransferInput related DB queries
24+
*
25+
* The store's ACS table must have the index on columns:
26+
* (store_id, migration_id, package_name, template_id_qualified_name,
27+
* reward_coupon_round) WHERE (reward_coupon_round IS NOT NULL)
28+
*/
29+
trait DbTransferInputQueries extends AcsQueries with AcsTables with LimitHelpers {
30+
self: TransferInputStore =>
31+
32+
protected def acsTableName: String
33+
protected def acsStoreId: AcsStoreId
34+
protected def domainMigrationId: Long
35+
protected def dbStorage: DbStorage
36+
37+
protected implicit def ec: ExecutionContext
38+
protected implicit def closeContext: CloseContext
39+
protected implicit def templateJsonDecoder: TemplateJsonDecoder
40+
41+
// List reward coupons sorted by round and calculated value.
42+
protected def listSortedRewardCoupons[C, TCid <: ContractId[?], T](
43+
companion: C,
44+
issuingRoundsMap: Map[Round, IssuingMiningRound],
45+
roundToIssuance: IssuingMiningRound => Option[BigDecimal],
46+
limit: Limit,
47+
ccValue: SQLActionBuilder = sql"rti.issuance",
48+
)(implicit
49+
companionClass: ContractCompanion[C, TCid, T],
50+
tc: TraceContext,
51+
): Future[Seq[(Contract[TCid, T], BigDecimal)]] = {
52+
val packageQualifiedName = companionClass.packageQualifiedName(companion)
53+
issuingRoundsMap
54+
.flatMap { case (round, contract) =>
55+
roundToIssuance(contract).map(round.number.longValue() -> _)
56+
}
57+
.map { case (round, issuance) =>
58+
sql"($round, $issuance)"
59+
}
60+
.reduceOption { (acc, next) =>
61+
(acc ++ sql"," ++ next).toActionBuilder
62+
} match {
63+
case None => Future.successful(Seq.empty) // no rounds = no results
64+
case Some(roundToIssuanceValues) =>
65+
for {
66+
result <- dbStorage.query(
67+
(sql"""
68+
with round_to_issuance(round, issuance) as (values """ ++ roundToIssuanceValues ++ sql""")
69+
select
70+
#${SelectFromAcsTableResult.sqlColumnsCommaSeparated()},""" ++ ccValue ++ sql"""
71+
from #$acsTableName acs join round_to_issuance rti on acs.reward_coupon_round = rti.round
72+
where acs.store_id = $acsStoreId
73+
and migration_id = $domainMigrationId
74+
and acs.package_name = ${packageQualifiedName.packageName}
75+
and acs.template_id_qualified_name = ${packageQualifiedName.qualifiedName}
76+
order by (acs.reward_coupon_round, -""" ++ ccValue ++ sql""")
77+
limit ${sqlLimit(limit)}""").toActionBuilder
78+
.as[(SelectFromAcsTableResult, BigDecimal)],
79+
s"listSorted:$packageQualifiedName",
80+
)
81+
} yield applyLimit(s"listSorted:$packageQualifiedName", limit, result).map {
82+
case (row, issuance) =>
83+
val contract = contractFromRow(companion)(row)
84+
contract -> issuance
85+
}
86+
}
87+
}
88+
}

apps/wallet/src/main/scala/org/lfdecentralizedtrust/splice/wallet/store/db/DbExternalPartyWalletStore.scala

Lines changed: 9 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,29 @@
33

44
package org.lfdecentralizedtrust.splice.wallet.store.db
55

6-
import com.daml.ledger.javaapi.data.codegen.ContractId
76
import org.lfdecentralizedtrust.splice.codegen.java.splice.validatorlicense as validatorCodegen
87
import org.lfdecentralizedtrust.splice.codegen.java.splice.round.IssuingMiningRound
98
import org.lfdecentralizedtrust.splice.codegen.java.splice.types.Round
109
import org.lfdecentralizedtrust.splice.environment.RetryProvider
1110
import org.lfdecentralizedtrust.splice.migration.DomainMigrationInfo
12-
import org.lfdecentralizedtrust.splice.store.MultiDomainAcsStore.ContractCompanion
13-
import org.lfdecentralizedtrust.splice.store.db.AcsQueries.SelectFromAcsTableResult
1411
import org.lfdecentralizedtrust.splice.store.db.StoreDescriptor
1512
import org.lfdecentralizedtrust.splice.store.db.{
1613
AcsInterfaceViewRowData,
1714
AcsQueries,
1815
AcsTables,
1916
DbAppStore,
17+
DbTransferInputQueries,
2018
}
2119
import org.lfdecentralizedtrust.splice.store.{Limit, LimitHelpers}
2220
import org.lfdecentralizedtrust.splice.util.{Contract, TemplateJsonDecoder}
2321
import org.lfdecentralizedtrust.splice.wallet.store.ExternalPartyWalletStore
2422
import com.digitalasset.canton.lifecycle.CloseContext
2523
import com.digitalasset.canton.logging.NamedLoggerFactory
2624
import com.digitalasset.canton.resource.DbStorage
27-
import com.digitalasset.canton.resource.DbStorage.Implicits.BuilderChain.*
2825
import com.digitalasset.canton.tracing.TraceContext
2926
import com.digitalasset.canton.util.ShowUtil.*
3027
import com.digitalasset.canton.topology.ParticipantId
3128
import org.lfdecentralizedtrust.splice.config.IngestionConfig
32-
import slick.jdbc.canton.ActionBasedSQLInterpolation.Implicits.actionBasedSQLInterpolationCanton
33-
import slick.jdbc.canton.SQLActionBuilder
3429

3530
import scala.concurrent.*
3631
import scala.jdk.OptionConverters.*
@@ -44,9 +39,9 @@ class DbExternalPartyWalletStore(
4439
participantId: ParticipantId,
4540
ingestionConfig: IngestionConfig,
4641
)(implicit
47-
ec: ExecutionContext,
48-
templateJsonDecoder: TemplateJsonDecoder,
49-
closeContext: CloseContext,
42+
override protected val ec: ExecutionContext,
43+
override protected val templateJsonDecoder: TemplateJsonDecoder,
44+
override protected val closeContext: CloseContext,
5045
) extends DbAppStore(
5146
storage = storage,
5247
acsTableName = WalletTables.externalPartyAcsTableName,
@@ -66,15 +61,17 @@ class DbExternalPartyWalletStore(
6661
ingestionConfig,
6762
)
6863
with ExternalPartyWalletStore
64+
with DbTransferInputQueries
6965
with AcsTables
7066
with AcsQueries
7167
with LimitHelpers {
7268

7369
import org.lfdecentralizedtrust.splice.store.db.AcsQueries.AcsStoreId
74-
import org.lfdecentralizedtrust.splice.util.FutureUnlessShutdownUtil.futureUnlessShutdownToFuture
7570

76-
private def acsStoreId: AcsStoreId = multiDomainAcsStore.acsStoreId
77-
private def domainMigrationId: Long = domainMigrationInfo.currentMigrationId
71+
override protected def acsStoreId: AcsStoreId = multiDomainAcsStore.acsStoreId
72+
override protected def domainMigrationId: Long = domainMigrationInfo.currentMigrationId
73+
override protected def acsTableName: String = WalletTables.externalPartyAcsTableName
74+
override protected def dbStorage: DbStorage = storage
7875

7976
override def toString: String =
8077
show"DbExternalPartyWalletStore(externalParty=${key.externalParty})"
@@ -102,51 +99,4 @@ class DbExternalPartyWalletStore(
10299
limit,
103100
)
104101

105-
private def listSortedRewardCoupons[C, TCid <: ContractId[?], T](
106-
companion: C,
107-
issuingRoundsMap: Map[Round, IssuingMiningRound],
108-
roundToIssuance: IssuingMiningRound => Option[BigDecimal],
109-
limit: Limit,
110-
ccValue: SQLActionBuilder = sql"rti.issuance",
111-
)(implicit
112-
companionClass: ContractCompanion[C, TCid, T],
113-
tc: TraceContext,
114-
): Future[Seq[(Contract[TCid, T], BigDecimal)]] = {
115-
val packageQualifiedName = companionClass.packageQualifiedName(companion)
116-
issuingRoundsMap
117-
.flatMap { case (round, contract) =>
118-
roundToIssuance(contract).map(round.number.longValue() -> _)
119-
}
120-
.map { case (round, issuance) =>
121-
sql"($round, $issuance)"
122-
}
123-
.reduceOption { (acc, next) =>
124-
(acc ++ sql"," ++ next).toActionBuilder
125-
} match {
126-
case None => Future.successful(Seq.empty) // no rounds = no results
127-
case Some(roundToIssuance) =>
128-
for {
129-
result <- storage.query(
130-
(sql"""
131-
with round_to_issuance(round, issuance) as (values """ ++ roundToIssuance ++ sql""")
132-
select
133-
#${SelectFromAcsTableResult.sqlColumnsCommaSeparated()},""" ++ ccValue ++ sql"""
134-
from #${WalletTables.externalPartyAcsTableName} acs join round_to_issuance rti on acs.reward_coupon_round = rti.round
135-
where acs.store_id = $acsStoreId
136-
and migration_id = $domainMigrationId
137-
and acs.package_name = ${packageQualifiedName.packageName}
138-
and acs.template_id_qualified_name = ${packageQualifiedName.qualifiedName}
139-
order by (acs.reward_coupon_round, -""" ++ ccValue ++ sql""")
140-
limit ${sqlLimit(limit)}""").toActionBuilder
141-
.as[(SelectFromAcsTableResult, BigDecimal)],
142-
s"listSorted:$packageQualifiedName",
143-
)
144-
} yield applyLimit(s"listSorted:$packageQualifiedName", limit, result).map {
145-
case (row, issuance) =>
146-
val contract = contractFromRow(companion)(row)
147-
contract -> issuance
148-
}
149-
}
150-
}
151-
152102
}

apps/wallet/src/main/scala/org/lfdecentralizedtrust/splice/wallet/store/db/DbUserWalletStore.scala

Lines changed: 9 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
package org.lfdecentralizedtrust.splice.wallet.store.db
55

6-
import com.daml.ledger.javaapi.data.codegen.ContractId
76
import com.daml.ledger.javaapi.data.codegen.json.JsonLfReader
87
import org.lfdecentralizedtrust.splice.codegen.java.splice.amulet as amuletCodegen
98
import org.lfdecentralizedtrust.splice.codegen.java.splice.amuletrules.TransferPreapproval
@@ -15,13 +14,14 @@ import org.lfdecentralizedtrust.splice.codegen.java.splice.wallet.subscriptions
1514
import org.lfdecentralizedtrust.splice.codegen.java.splice.wallet.transferpreapproval.TransferPreapprovalProposal
1615
import org.lfdecentralizedtrust.splice.environment.RetryProvider
1716
import org.lfdecentralizedtrust.splice.migration.DomainMigrationInfo
18-
import org.lfdecentralizedtrust.splice.store.MultiDomainAcsStore.{ContractCompanion, QueryResult}
17+
import org.lfdecentralizedtrust.splice.store.MultiDomainAcsStore.QueryResult
1918
import org.lfdecentralizedtrust.splice.store.db.AcsQueries.{AcsStoreId, SelectFromAcsTableResult}
2019
import org.lfdecentralizedtrust.splice.store.db.StoreDescriptor
2120
import org.lfdecentralizedtrust.splice.store.db.{
2221
AcsQueries,
2322
AcsTables,
2423
DbTxLogAppStore,
24+
DbTransferInputQueries,
2525
TxLogQueries,
2626
}
2727
import org.lfdecentralizedtrust.splice.store.{Limit, LimitHelpers, PageLimit, TxLogStore}
@@ -46,7 +46,6 @@ import com.digitalasset.canton.resource.DbStorage.Implicits.BuilderChain.toSQLAc
4646
import com.digitalasset.canton.topology.{ParticipantId, PartyId}
4747
import org.lfdecentralizedtrust.splice.config.IngestionConfig
4848
import org.lfdecentralizedtrust.splice.store.db.TxLogQueries.TxLogStoreId
49-
import slick.jdbc.canton.SQLActionBuilder
5049

5150
import scala.concurrent.*
5251
import scala.jdk.OptionConverters.*
@@ -60,9 +59,9 @@ class DbUserWalletStore(
6059
participantId: ParticipantId,
6160
ingestionConfig: IngestionConfig,
6261
)(implicit
63-
ec: ExecutionContext,
64-
templateJsonDecoder: TemplateJsonDecoder,
65-
closeContext: CloseContext,
62+
override protected val ec: ExecutionContext,
63+
override protected val templateJsonDecoder: TemplateJsonDecoder,
64+
override protected val closeContext: CloseContext,
6665
) extends DbTxLogAppStore[TxLogEntry](
6766
storage = storage,
6867
acsTableName = WalletTables.acsTableName,
@@ -98,6 +97,7 @@ class DbUserWalletStore(
9897
ingestionConfig,
9998
)
10099
with UserWalletStore
100+
with DbTransferInputQueries
101101
with AcsTables
102102
with AcsQueries
103103
with TxLogQueries[TxLogEntry]
@@ -106,9 +106,11 @@ class DbUserWalletStore(
106106
import multiDomainAcsStore.waitUntilAcsIngested
107107
import org.lfdecentralizedtrust.splice.util.FutureUnlessShutdownUtil.futureUnlessShutdownToFuture
108108

109-
private def acsStoreId: AcsStoreId = multiDomainAcsStore.acsStoreId
109+
override protected def acsStoreId: AcsStoreId = multiDomainAcsStore.acsStoreId
110110
private def txLogStoreId: TxLogStoreId = multiDomainAcsStore.txLogStoreId
111111
override def domainMigrationId: Long = domainMigrationInfo.currentMigrationId
112+
override protected def acsTableName: String = WalletTables.acsTableName
113+
override protected def dbStorage: DbStorage = storage
112114

113115
override def toString: String = show"DbUserWalletStore(endUserParty=${key.endUserParty})"
114116

@@ -188,53 +190,6 @@ class DbUserWalletStore(
188190
ccValue = sql"rti.issuance * acs.reward_coupon_weight",
189191
)
190192

191-
private def listSortedRewardCoupons[C, TCid <: ContractId[?], T](
192-
companion: C,
193-
issuingRoundsMap: Map[Round, IssuingMiningRound],
194-
roundToIssuance: IssuingMiningRound => Option[BigDecimal],
195-
limit: Limit,
196-
ccValue: SQLActionBuilder = sql"rti.issuance",
197-
)(implicit
198-
companionClass: ContractCompanion[C, TCid, T],
199-
traceContext: TraceContext,
200-
): Future[Seq[(Contract[TCid, T], BigDecimal)]] = {
201-
val packageQualifiedName = companionClass.packageQualifiedName(companion)
202-
issuingRoundsMap
203-
.flatMap { case (round, contract) =>
204-
roundToIssuance(contract).map(round.number.longValue() -> _)
205-
}
206-
.map { case (round, issuance) =>
207-
sql"($round, $issuance)"
208-
}
209-
.reduceOption { (acc, next) =>
210-
(acc ++ sql"," ++ next).toActionBuilder
211-
} match {
212-
case None => Future.successful(Seq.empty) // no rounds = no results
213-
case Some(roundToIssuance) =>
214-
for {
215-
result <- storage.query(
216-
(sql"""
217-
with round_to_issuance(round, issuance) as (values """ ++ roundToIssuance ++ sql""")
218-
select
219-
#${SelectFromAcsTableResult.sqlColumnsCommaSeparated()},""" ++ ccValue ++ sql"""
220-
from #${WalletTables.acsTableName} acs join round_to_issuance rti on acs.reward_coupon_round = rti.round
221-
where acs.store_id = $acsStoreId
222-
and migration_id = $domainMigrationId
223-
and acs.package_name = ${packageQualifiedName.packageName}
224-
and acs.template_id_qualified_name = ${packageQualifiedName.qualifiedName}
225-
order by (acs.reward_coupon_round, -""" ++ ccValue ++ sql""")
226-
limit ${sqlLimit(limit)}""").toActionBuilder
227-
.as[(SelectFromAcsTableResult, BigDecimal)],
228-
s"listSorted:$packageQualifiedName",
229-
)
230-
} yield applyLimit(s"listSorted:$packageQualifiedName", limit, result).map {
231-
case (row, issuance) =>
232-
val contract = contractFromRow(companion)(row)
233-
contract -> issuance
234-
}
235-
}
236-
}
237-
238193
override def listTransactions(
239194
beginAfterEventIdO: Option[String],
240195
limit: PageLimit,

0 commit comments

Comments
 (0)