|
@ -12,6 +12,7 @@ import com.xsn.explorer.models.{Address, Balance, Transaction} |
|
|
import com.xsn.explorer.util.Extensions.ListOptionExt |
|
|
import com.xsn.explorer.util.Extensions.ListOptionExt |
|
|
import javax.inject.Inject |
|
|
import javax.inject.Inject |
|
|
import org.scalactic.Good |
|
|
import org.scalactic.Good |
|
|
|
|
|
import org.slf4j.LoggerFactory |
|
|
import play.api.db.Database |
|
|
import play.api.db.Database |
|
|
|
|
|
|
|
|
class LedgerPostgresDataHandler @Inject() ( |
|
|
class LedgerPostgresDataHandler @Inject() ( |
|
@ -23,6 +24,8 @@ class LedgerPostgresDataHandler @Inject() ( |
|
|
extends LedgerBlockingDataHandler |
|
|
extends LedgerBlockingDataHandler |
|
|
with AnormPostgresDataHandler { |
|
|
with AnormPostgresDataHandler { |
|
|
|
|
|
|
|
|
|
|
|
private val logger = LoggerFactory.getLogger(this.getClass) |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Push a block into the database chain, note that even if the block is supposed |
|
|
* Push a block into the database chain, note that even if the block is supposed |
|
|
* to have a next block, we remove the link because that block is not stored yet. |
|
|
* to have a next block, we remove the link because that block is not stored yet. |
|
@ -31,6 +34,7 @@ class LedgerPostgresDataHandler @Inject() ( |
|
|
block: Block, |
|
|
block: Block, |
|
|
transactions: List[Transaction]): ApplicationResult[Unit] = { |
|
|
transactions: List[Transaction]): ApplicationResult[Unit] = { |
|
|
|
|
|
|
|
|
|
|
|
val start = System.currentTimeMillis() |
|
|
val result = withTransaction { implicit conn => |
|
|
val result = withTransaction { implicit conn => |
|
|
val result = for { |
|
|
val result = for { |
|
|
_ <- upsertBlockCascade(block.copy(nextBlockhash = None), transactions) |
|
|
_ <- upsertBlockCascade(block.copy(nextBlockhash = None), transactions) |
|
@ -47,6 +51,8 @@ class LedgerPostgresDataHandler @Inject() ( |
|
|
case _ => e |
|
|
case _ => e |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
val took = System.currentTimeMillis() - start |
|
|
|
|
|
logger.info(s"Pushing block = ${block.hash}, took $took ms") |
|
|
result.badMap { _.map(fromError) } |
|
|
result.badMap { _.map(fromError) } |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -75,11 +81,7 @@ class LedgerPostgresDataHandler @Inject() ( |
|
|
|
|
|
|
|
|
// balances |
|
|
// balances |
|
|
balanceList = balances(transactions) |
|
|
balanceList = balances(transactions) |
|
|
|
|
|
_ <- insertBalanceBatch(balanceList).toList.everything |
|
|
_ <- balanceList |
|
|
|
|
|
.map { b => balancePostgresDAO.upsert(b) } |
|
|
|
|
|
.toList |
|
|
|
|
|
.everything |
|
|
|
|
|
|
|
|
|
|
|
// compute aggregated amount |
|
|
// compute aggregated amount |
|
|
delta = balanceList.map(_.available).sum |
|
|
delta = balanceList.map(_.available).sum |
|
@ -116,6 +118,16 @@ class LedgerPostgresDataHandler @Inject() ( |
|
|
} yield () |
|
|
} yield () |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private def insertBalanceBatch(balanceList: Iterable[Balance])(implicit conn: Connection) = { |
|
|
|
|
|
val start = System.currentTimeMillis() |
|
|
|
|
|
val result = balanceList.map { b => balancePostgresDAO.upsert(b) } |
|
|
|
|
|
|
|
|
|
|
|
val took = System.currentTimeMillis() - start |
|
|
|
|
|
logger.info(s"Inserting balance batch, size = ${balanceList.size}, took = $took ms") |
|
|
|
|
|
|
|
|
|
|
|
result |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
private def spendMap(transactions: List[Transaction]): Map[Address, BigDecimal] = { |
|
|
private def spendMap(transactions: List[Transaction]): Map[Address, BigDecimal] = { |
|
|
transactions |
|
|
transactions |
|
|
.map(_.inputs) |
|
|
.map(_.inputs) |
|
@ -139,6 +151,7 @@ class LedgerPostgresDataHandler @Inject() ( |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private def balances(transactions: List[Transaction]) = { |
|
|
private def balances(transactions: List[Transaction]) = { |
|
|
|
|
|
val start = System.currentTimeMillis() |
|
|
val spentList = spendMap(transactions).map { case (address, spent) => |
|
|
val spentList = spendMap(transactions).map { case (address, spent) => |
|
|
Balance(address, spent = spent) |
|
|
Balance(address, spent = spent) |
|
|
} |
|
|
} |
|
@ -147,10 +160,14 @@ class LedgerPostgresDataHandler @Inject() ( |
|
|
Balance(address, received = received) |
|
|
Balance(address, received = received) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
(spentList ++ receiveList) |
|
|
val result = (spentList ++ receiveList) |
|
|
.groupBy(_.address) |
|
|
.groupBy(_.address) |
|
|
.mapValues { _.reduce(mergeBalances) } |
|
|
.mapValues { _.reduce(mergeBalances) } |
|
|
.values |
|
|
.values |
|
|
|
|
|
|
|
|
|
|
|
val took = System.currentTimeMillis() - start |
|
|
|
|
|
logger.info(s"Computing balances for transaction batch, size = ${transactions.size}, took = $took ms") |
|
|
|
|
|
result |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private def mergeBalances(a: Balance, b: Balance): Balance = { |
|
|
private def mergeBalances(a: Balance, b: Balance): Balance = { |
|
|