Browse Source

server: Return statistics even if masternodes or difficulty aren't available

master
Alexis Hernandez 6 years ago
parent
commit
516dd402d1
  1. 26
      server/app/com/xsn/explorer/services/StatisticsService.scala
  2. 82
      server/test/controllers/StatisticsControllerSpec.scala

26
server/app/com/xsn/explorer/services/StatisticsService.scala

@ -1,11 +1,10 @@
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.StatisticsFutureDataHandler
import com.xsn.explorer.models.StatisticsDetails
import javax.inject.Inject
import org.scalactic.{Bad, Good}
import scala.concurrent.ExecutionContext
@ -18,20 +17,23 @@ class StatisticsService @Inject() (
def getStatistics(): FutureApplicationResult[StatisticsDetails] = {
val dbStats = statisticsFutureDataHandler.getStatistics()
val rpcStats = xsnService.getMasternodeCount()
val difficulty = xsnService.getDifficulty()
val difficultyF = xsnService.getDifficulty()
val result = for {
stats <- dbStats.toFutureOr
count <- rpcStats.map {
case Good(count) => Good(Some(count))
case Bad(_) => Good(None)
}.toFutureOr
diff <- difficulty.map {
case Good(difficulty) => Good(Some(difficulty))
case Bad(_) => Good(None)
}.toFutureOr
} yield StatisticsDetails(stats, count, diff)
count <- discardErrors(rpcStats).toFutureOr
difficulty <- discardErrors(difficultyF).toFutureOr
} yield StatisticsDetails(stats, count, difficulty)
result.toFuture
}
private def discardErrors[T](value: FutureApplicationResult[T]): FutureApplicationResult[Option[T]] = {
value
.map {
case Good(result) => Good(Some(result))
case Bad(_) => Good(None)
}
.recover { case _: Throwable => Good(None) }
}
}

82
server/test/controllers/StatisticsControllerSpec.scala

@ -1,12 +1,14 @@
package controllers
import com.alexitc.playsonify.core.{ApplicationResult, FutureApplicationResult}
import com.alexitc.playsonify.core.ApplicationResult
import com.xsn.explorer.data.StatisticsBlockingDataHandler
import com.xsn.explorer.helpers.DummyXSNService
import com.xsn.explorer.errors.XSNUnexpectedResponseError
import com.xsn.explorer.models.Statistics
import com.xsn.explorer.services.XSNService
import controllers.common.MyAPISpec
import org.scalactic.Good
import org.mockito.Mockito.{mock => _, _}
import org.scalactic.{Bad, Good}
import org.scalatest.mockito.MockitoSugar._
import play.api.inject.bind
import play.api.test.Helpers._
@ -24,14 +26,7 @@ class StatisticsControllerSpec extends MyAPISpec {
override def getStatistics(): ApplicationResult[Statistics] = Good(stats)
}
val xsnService = new DummyXSNService {
override def getMasternodeCount(): FutureApplicationResult[Int] = {
Future.successful(Good(1000))
}
override def getDifficulty(): FutureApplicationResult[BigDecimal] = {
Future.successful(Good(129.1827211827212))
}
}
val xsnService = mock[XSNService]
override val application = guiceApplicationBuilder
.overrides(bind[StatisticsBlockingDataHandler].to(dataHandler))
@ -40,6 +35,57 @@ class StatisticsControllerSpec extends MyAPISpec {
"GET /stats" should {
"return the server statistics" in {
val masternodes = 1000
val difficulty = BigDecimal("129.1827211827212")
when(xsnService.getMasternodeCount()).thenReturn(Future.successful(Good(masternodes)))
when(xsnService.getDifficulty()).thenReturn(Future.successful(Good(difficulty)))
val response = GET("/stats")
status(response) mustEqual OK
val json = contentAsJson(response)
(json \ "blocks").as[Int] mustEqual stats.blocks
(json \ "transactions").as[Int] mustEqual stats.transactions
(json \ "totalSupply").as[BigDecimal] mustEqual stats.totalSupply.get
(json \ "circulatingSupply").as[BigDecimal] mustEqual stats.circulatingSupply.get
(json \ "masternodes").as[Int] mustEqual masternodes
(json \ "difficulty").as[BigDecimal] mustEqual difficulty
}
"return the stats even if getting masternodes throws an exception" in {
val difficulty = BigDecimal("129.1827211827212")
when(xsnService.getMasternodeCount()).thenReturn(Future.failed(new Exception))
when(xsnService.getDifficulty()).thenReturn(Future.successful(Good(difficulty)))
missingMasternodesTest(difficulty)
}
"return the stats even if the masternodes aren't available" in {
val difficulty = BigDecimal("129.1827211827212")
when(xsnService.getMasternodeCount()).thenReturn(Future.successful(Bad(XSNUnexpectedResponseError).accumulating))
when(xsnService.getDifficulty()).thenReturn(Future.successful(Good(difficulty)))
missingMasternodesTest(difficulty)
}
"return the stats even if getting the difficulty throws an exception" in {
val masternodes = 1000
when(xsnService.getMasternodeCount()).thenReturn(Future.successful(Good(masternodes)))
when(xsnService.getDifficulty()).thenReturn(Future.failed(new Exception))
missingDifficultyTest(masternodes)
}
"return the stats even if the difficulty isn't available" in {
val masternodes = 1000
when(xsnService.getMasternodeCount()).thenReturn(Future.successful(Good(masternodes)))
when(xsnService.getDifficulty()).thenReturn(Future.successful(Bad(XSNUnexpectedResponseError).accumulating))
missingDifficultyTest(masternodes)
}
}
private def missingMasternodesTest(difficulty: BigDecimal) = {
val response = GET("/stats")
status(response) mustEqual OK
@ -48,8 +94,18 @@ class StatisticsControllerSpec extends MyAPISpec {
(json \ "transactions").as[Int] mustEqual stats.transactions
(json \ "totalSupply").as[BigDecimal] mustEqual stats.totalSupply.get
(json \ "circulatingSupply").as[BigDecimal] mustEqual stats.circulatingSupply.get
(json \ "masternodes").as[Int] mustEqual 1000
(json \ "difficulty").as[BigDecimal] mustEqual 129.1827211827212
(json \ "difficulty").as[BigDecimal] mustEqual difficulty
}
private def missingDifficultyTest(masternodes: Int) = {
val response = GET("/stats")
status(response) mustEqual OK
val json = contentAsJson(response)
(json \ "blocks").as[Int] mustEqual stats.blocks
(json \ "transactions").as[Int] mustEqual stats.transactions
(json \ "totalSupply").as[BigDecimal] mustEqual stats.totalSupply.get
(json \ "circulatingSupply").as[BigDecimal] mustEqual stats.circulatingSupply.get
(json \ "masternodes").as[Int] mustEqual masternodes
}
}

Loading…
Cancel
Save