From cbdfaf06e970c1943e0fde091ff6b5bb53286787 Mon Sep 17 00:00:00 2001 From: Alexis Hernandez Date: Thu, 12 Apr 2018 23:30:34 -0500 Subject: [PATCH] server: Update Statistics to be loaded from StatisticsDataHandler --- .../explorer/data/StatisticsDataHandler.scala | 13 ++++++++++ .../anorm/StatisticsPostgresDataHandler.scala | 22 ++++++++++++++++ .../anorm/dao/StatisticsPostgresDAO.scala | 25 +++++++++++++++++++ .../anorm/parsers/StatisticsParsers.scala | 18 +++++++++++++ .../async/StatisticsFutureDataHandler.scala | 20 +++++++++++++++ .../com/xsn/explorer/models/Statistics.scala | 2 +- .../explorer/modules/DataHandlerModule.scala | 5 ++-- .../explorer/services/StatisticsService.scala | 13 +++------- 8 files changed, 105 insertions(+), 13 deletions(-) create mode 100644 server/app/com/xsn/explorer/data/StatisticsDataHandler.scala create mode 100644 server/app/com/xsn/explorer/data/anorm/StatisticsPostgresDataHandler.scala create mode 100644 server/app/com/xsn/explorer/data/anorm/dao/StatisticsPostgresDAO.scala create mode 100644 server/app/com/xsn/explorer/data/anorm/parsers/StatisticsParsers.scala create mode 100644 server/app/com/xsn/explorer/data/async/StatisticsFutureDataHandler.scala diff --git a/server/app/com/xsn/explorer/data/StatisticsDataHandler.scala b/server/app/com/xsn/explorer/data/StatisticsDataHandler.scala new file mode 100644 index 0000000..910b770 --- /dev/null +++ b/server/app/com/xsn/explorer/data/StatisticsDataHandler.scala @@ -0,0 +1,13 @@ +package com.xsn.explorer.data + +import com.alexitc.playsonify.core.ApplicationResult +import com.xsn.explorer.models.Statistics + +import scala.language.higherKinds + +trait StatisticsDataHandler[F[_]] { + + def getStatistics(): F[Statistics] +} + +trait StatisticsBlockingDataHandler extends StatisticsDataHandler[ApplicationResult] diff --git a/server/app/com/xsn/explorer/data/anorm/StatisticsPostgresDataHandler.scala b/server/app/com/xsn/explorer/data/anorm/StatisticsPostgresDataHandler.scala new file mode 100644 index 0000000..519bcaa --- /dev/null +++ b/server/app/com/xsn/explorer/data/anorm/StatisticsPostgresDataHandler.scala @@ -0,0 +1,22 @@ +package com.xsn.explorer.data.anorm + +import javax.inject.Inject + +import com.alexitc.playsonify.core.ApplicationResult +import com.xsn.explorer.data.StatisticsBlockingDataHandler +import com.xsn.explorer.data.anorm.dao.StatisticsPostgresDAO +import com.xsn.explorer.models.Statistics +import org.scalactic.Good +import play.api.db.Database + +class StatisticsPostgresDataHandler @Inject() ( + override val database: Database, + statisticsDAO: StatisticsPostgresDAO) + extends StatisticsBlockingDataHandler + with AnormPostgresDataHandler { + + override def getStatistics(): ApplicationResult[Statistics] = withConnection { implicit conn => + val result = statisticsDAO.getStatistics + Good(result) + } +} diff --git a/server/app/com/xsn/explorer/data/anorm/dao/StatisticsPostgresDAO.scala b/server/app/com/xsn/explorer/data/anorm/dao/StatisticsPostgresDAO.scala new file mode 100644 index 0000000..7dfe2d1 --- /dev/null +++ b/server/app/com/xsn/explorer/data/anorm/dao/StatisticsPostgresDAO.scala @@ -0,0 +1,25 @@ +package com.xsn.explorer.data.anorm.dao + +import java.sql.Connection + +import anorm._ +import com.xsn.explorer.data.anorm.parsers.StatisticsParsers +import com.xsn.explorer.models.Statistics + +class StatisticsPostgresDAO { + + def getStatistics(implicit conn: Connection): Statistics = { + SQL( + """ + |SELECT + | (SELECT SUM(available) FROM balances) AS total_supply, + | ( + | SELECT SUM(available) FROM balances + | WHERE address NOT IN (SELECT address FROM hidden_addresses) + | ) AS circulating_supply, + | (SELECT COUNT(*) FROM transactions) AS transactions, + | (SELECT MAX(height) FROM blocks) AS blocks + """.stripMargin + ).as(StatisticsParsers.parseStatistics.single) + } +} diff --git a/server/app/com/xsn/explorer/data/anorm/parsers/StatisticsParsers.scala b/server/app/com/xsn/explorer/data/anorm/parsers/StatisticsParsers.scala new file mode 100644 index 0000000..e00de5e --- /dev/null +++ b/server/app/com/xsn/explorer/data/anorm/parsers/StatisticsParsers.scala @@ -0,0 +1,18 @@ +package com.xsn.explorer.data.anorm.parsers + +import anorm.SqlParser._ +import anorm._ +import com.xsn.explorer.models.Statistics + +object StatisticsParsers { + + val parseBlocks = int("blocks") + val parseTransactions = int("transactions") + val parseTotalSupply = get[BigDecimal]("total_supply") + val parseCirculatingSupply = get[BigDecimal]("circulating_supply") + + val parseStatistics = (parseBlocks ~ parseTransactions ~ parseTotalSupply ~ parseCirculatingSupply).map { + case blocks ~ transactions ~ totalSupply ~ circulatingSupply => + Statistics(blocks, transactions, totalSupply, circulatingSupply) + } +} diff --git a/server/app/com/xsn/explorer/data/async/StatisticsFutureDataHandler.scala b/server/app/com/xsn/explorer/data/async/StatisticsFutureDataHandler.scala new file mode 100644 index 0000000..2148ad6 --- /dev/null +++ b/server/app/com/xsn/explorer/data/async/StatisticsFutureDataHandler.scala @@ -0,0 +1,20 @@ +package com.xsn.explorer.data.async + +import javax.inject.Inject + +import com.alexitc.playsonify.core.FutureApplicationResult +import com.xsn.explorer.data.{StatisticsBlockingDataHandler, StatisticsDataHandler} +import com.xsn.explorer.executors.DatabaseExecutionContext +import com.xsn.explorer.models.Statistics + +import scala.concurrent.Future + +class StatisticsFutureDataHandler @Inject() ( + blockingDataHandler: StatisticsBlockingDataHandler)( + implicit ec: DatabaseExecutionContext) + extends StatisticsDataHandler[FutureApplicationResult] { + + override def getStatistics(): FutureApplicationResult[Statistics] = Future { + blockingDataHandler.getStatistics() + } +} diff --git a/server/app/com/xsn/explorer/models/Statistics.scala b/server/app/com/xsn/explorer/models/Statistics.scala index df9f716..346a7d4 100644 --- a/server/app/com/xsn/explorer/models/Statistics.scala +++ b/server/app/com/xsn/explorer/models/Statistics.scala @@ -3,7 +3,7 @@ package com.xsn.explorer.models import play.api.libs.json.{Json, Writes} case class Statistics( - height: Height, + blocks: Int, transactions: Int, totalSupply: BigDecimal, circulatingSupply: BigDecimal) diff --git a/server/app/com/xsn/explorer/modules/DataHandlerModule.scala b/server/app/com/xsn/explorer/modules/DataHandlerModule.scala index e8b6c4e..4d7d62b 100644 --- a/server/app/com/xsn/explorer/modules/DataHandlerModule.scala +++ b/server/app/com/xsn/explorer/modules/DataHandlerModule.scala @@ -1,13 +1,14 @@ package com.xsn.explorer.modules import com.google.inject.AbstractModule -import com.xsn.explorer.data.anorm.{BalancePostgresDataHandler, BlockPostgresDataHandler} -import com.xsn.explorer.data.{BalanceBlockingDataHandler, BlockBlockingDataHandler} +import com.xsn.explorer.data.anorm.{BalancePostgresDataHandler, BlockPostgresDataHandler, StatisticsPostgresDataHandler} +import com.xsn.explorer.data.{BalanceBlockingDataHandler, BlockBlockingDataHandler, StatisticsBlockingDataHandler} class DataHandlerModule extends AbstractModule { override def configure(): Unit = { bind(classOf[BlockBlockingDataHandler]).to(classOf[BlockPostgresDataHandler]) bind(classOf[BalanceBlockingDataHandler]).to(classOf[BalancePostgresDataHandler]) + bind(classOf[StatisticsBlockingDataHandler]).to(classOf[StatisticsPostgresDataHandler]) } } diff --git a/server/app/com/xsn/explorer/services/StatisticsService.scala b/server/app/com/xsn/explorer/services/StatisticsService.scala index 3fd507d..548d594 100644 --- a/server/app/com/xsn/explorer/services/StatisticsService.scala +++ b/server/app/com/xsn/explorer/services/StatisticsService.scala @@ -3,23 +3,16 @@ package com.xsn.explorer.services import javax.inject.Inject import com.alexitc.playsonify.core.FutureApplicationResult -import com.alexitc.playsonify.core.FutureOr.Implicits.FutureOps -import com.xsn.explorer.data.async.BalanceFutureDataHandler +import com.xsn.explorer.data.async.StatisticsFutureDataHandler import com.xsn.explorer.models.Statistics import scala.concurrent.ExecutionContext class StatisticsService @Inject() ( - xsnService: XSNService, - balanceFutureDataHandler: BalanceFutureDataHandler)( + statisticsFutureDataHandler: StatisticsFutureDataHandler)( implicit ec: ExecutionContext) { def getStatistics(): FutureApplicationResult[Statistics] = { - val result = for { - server <- xsnService.getServerStatistics().toFutureOr - circulatingSupply <- balanceFutureDataHandler.getCirculatingSupply().toFutureOr - } yield Statistics(server.height, server.transactions, server.totalSupply, circulatingSupply) - - result.toFuture + statisticsFutureDataHandler.getStatistics() } }