Browse Source

server: Remove the FirstBlockSynchronizerTask

The same job can be done by the BackwardsSynchronizerTask, there is no
need to keep both.
scalafmt-draft v2018.06.10
Alexis Hernandez 7 years ago
parent
commit
032fac4378
  1. 124
      server/app/com/xsn/explorer/tasks/FirstBlockSynchronizerTask.scala
  2. 9
      server/app/com/xsn/explorer/tasks/SQSSeederTask.scala

124
server/app/com/xsn/explorer/tasks/FirstBlockSynchronizerTask.scala

@ -1,124 +0,0 @@
package com.xsn.explorer.tasks
import javax.inject.{Inject, Singleton}
import com.alexitc.playsonify.core.FutureApplicationResult
import com.alexitc.playsonify.core.FutureOr.Implicits.{FutureListOps, FutureOps, OrOps}
import com.xsn.explorer.data.DatabaseSeeder
import com.xsn.explorer.data.async.{BlockFutureDataHandler, DatabaseFutureSeeder}
import com.xsn.explorer.errors.BlockNotFoundError
import com.xsn.explorer.models.{Blockhash, Height}
import com.xsn.explorer.services.{TransactionService, XSNService}
import org.scalactic.{Bad, Good, One, Or}
import org.slf4j.LoggerFactory
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.control.NonFatal
/**
* The database might start to be filled from a block different to the genesis one.
*
* This task helps to sync it from the first saved block backwards to the genesis one.
*/
@Singleton
class FirstBlockSynchronizerTask @Inject() (
xsnService: XSNService,
transactionService: TransactionService,
blockDataHandler: BlockFutureDataHandler,
databaseSeeder: DatabaseFutureSeeder) {
private val logger = LoggerFactory.getLogger(this.getClass)
private val lock = new Object
/**
* TODO: Until https://github.com/X9Developers/XSN/issues/32 is fixed, ignore the genesis block.
*/
private val FirstBlockHeight = Height(1)
private var running = false
def sync(): Unit = {
if (running) {
()
} else {
lock.synchronized {
if (running) {
()
} else {
running = true
tryToSync().onComplete { _ =>
running = false
}
}
}
}
}
private def tryToSync() = {
val futureOr = for {
firstBlock <- blockDataHandler.getFirstBlock().toFutureOr
previous <- Or.from(firstBlock.previousBlockhash, One(BlockNotFoundError)).toFutureOr
_ <- {
if (firstBlock.height == FirstBlockHeight) {
// no sync required
Future.successful(Good(()))
} else {
// sync
logger.info(s"Sync required until block ${firstBlock.height.int}")
val r = doSync(previous)
r.foreach {
case Good(_) =>
logger.info("Sync completed")
case _ => ()
}
r
}
}.toFutureOr
} yield ()
val result = futureOr.toFuture
result.foreach {
case Bad(errors) =>
logger.error(s"Failed to sync blocks, errors = $errors")
case _ => ()
}
result.recover {
case NonFatal(ex) =>
logger.error(s"Failed to sync blocks", ex)
}
result
}
private def doSync(blockhash: Blockhash): FutureApplicationResult[Unit] = {
val result = for {
block <- xsnService.getBlock(blockhash).toFutureOr
transactions <- block.transactions.map(transactionService.getTransaction).toFutureOr
command = DatabaseSeeder.CreateBlockCommand(block, transactions)
_ <- databaseSeeder.newBlock(command).toFutureOr
_ = logger.debug(s"Block ${block.height.int} saved")
_ <- block
.previousBlockhash
.filter(_ => block.height.int > FirstBlockHeight.int)
.map { previous =>
doSync(previous)
}
.getOrElse {
logger.debug(s"No more blocks to sync")
Future.successful(Good(()))
}
.toFutureOr
} yield ()
result.toFuture
}
}

9
server/app/com/xsn/explorer/tasks/SQSSeederTask.scala

@ -22,7 +22,6 @@ import scala.util.{Failure, Success}
class SQSSeederTask @Inject() ( class SQSSeederTask @Inject() (
config: SeederConfig, config: SeederConfig,
blockEventsProcessor: BlockEventsProcessor, blockEventsProcessor: BlockEventsProcessor,
firstBlockSynchronizerTask: FirstBlockSynchronizerTask,
backwardsSynchronizerTask: BackwardsSynchronizerTask)( backwardsSynchronizerTask: BackwardsSynchronizerTask)(
implicit sqs: AmazonSQSAsync, implicit sqs: AmazonSQSAsync,
materializer: Materializer) { materializer: Materializer) {
@ -92,14 +91,12 @@ class SQSSeederTask @Inject() (
} }
private def onBlockResult(eventResult: BlockEventsProcessor.Result) = eventResult match { private def onBlockResult(eventResult: BlockEventsProcessor.Result) = eventResult match {
case BlockEventsProcessor.FirstBlockCreated(_) => case BlockEventsProcessor.FirstBlockCreated(block) =>
firstBlockSynchronizerTask.sync() backwardsSynchronizerTask.sync(block)
case BlockEventsProcessor.NewBlockAppended(_) => case BlockEventsProcessor.NewBlockAppended(_) => ()
firstBlockSynchronizerTask.sync()
case BlockEventsProcessor.RechainDone(_, newBlock) => case BlockEventsProcessor.RechainDone(_, newBlock) =>
firstBlockSynchronizerTask.sync()
backwardsSynchronizerTask.sync(newBlock) backwardsSynchronizerTask.sync(newBlock)
case BlockEventsProcessor.MissingBlockProcessed(block) => case BlockEventsProcessor.MissingBlockProcessed(block) =>

Loading…
Cancel
Save