From d076fe151e9008a126861e7cf5a206edb63e8b37 Mon Sep 17 00:00:00 2001 From: Alexis Hernandez Date: Sat, 7 Apr 2018 12:53:44 -0500 Subject: [PATCH] server: Allow to delete blocks by hash --- .../xsn/explorer/data/BlockDataHandler.scala | 2 ++ .../data/anorm/BlockPostgresDataHandler.scala | 5 +++++ .../data/anorm/dao/BlockPostgresDAO.scala | 13 +++++++++++++ .../data/BlockPostgresDataHandlerSpec.scala | 18 ++++++++++++++++++ 4 files changed, 38 insertions(+) diff --git a/server/app/com/xsn/explorer/data/BlockDataHandler.scala b/server/app/com/xsn/explorer/data/BlockDataHandler.scala index d48c580..bd1f717 100644 --- a/server/app/com/xsn/explorer/data/BlockDataHandler.scala +++ b/server/app/com/xsn/explorer/data/BlockDataHandler.scala @@ -11,6 +11,8 @@ trait BlockDataHandler[F[_]] { def create(block: Block): F[Block] def getBy(blockhash: Blockhash): F[Block] + + def delete(blockhash: Blockhash): F[Block] } trait BlockBlockingDataHandler extends BlockDataHandler[ApplicationResult] diff --git a/server/app/com/xsn/explorer/data/anorm/BlockPostgresDataHandler.scala b/server/app/com/xsn/explorer/data/anorm/BlockPostgresDataHandler.scala index a603e8f..8c3cfbe 100644 --- a/server/app/com/xsn/explorer/data/anorm/BlockPostgresDataHandler.scala +++ b/server/app/com/xsn/explorer/data/anorm/BlockPostgresDataHandler.scala @@ -26,4 +26,9 @@ class BlockPostgresDataHandler @Inject() ( val maybe = blockPostgresDAO.getBy(blockhash) Or.from(maybe, One(BlockNotFoundError)) } + + override def delete(blockhash: Blockhash): ApplicationResult[Block] = database.withConnection { implicit conn => + val maybe = blockPostgresDAO.delete(blockhash) + Or.from(maybe, One(BlockNotFoundError)) + } } diff --git a/server/app/com/xsn/explorer/data/anorm/dao/BlockPostgresDAO.scala b/server/app/com/xsn/explorer/data/anorm/dao/BlockPostgresDAO.scala index 1b1a45b..6b6e595 100644 --- a/server/app/com/xsn/explorer/data/anorm/dao/BlockPostgresDAO.scala +++ b/server/app/com/xsn/explorer/data/anorm/dao/BlockPostgresDAO.scala @@ -70,4 +70,17 @@ class BlockPostgresDAO { "hash" -> blockhash.string ).as(parseBlock.singleOpt).flatten } + + def delete(blockhash: Blockhash)(implicit conn: Connection): Option[Block] = { + SQL( + """ + |DELETE FROM blocks + |WHERE hash = {hash} + |RETURNING hash, previous_blockhash, next_blockhash, tpos_contract, merkle_root, size, + | height, version, time, median_time, nonce, bits, chainwork, difficulty + """.stripMargin + ).on( + "hash" -> blockhash.string + ).as(parseBlock.singleOpt).flatten + } } diff --git a/server/test/com/xsn/explorer/data/BlockPostgresDataHandlerSpec.scala b/server/test/com/xsn/explorer/data/BlockPostgresDataHandlerSpec.scala index 98a27e7..e513cad 100644 --- a/server/test/com/xsn/explorer/data/BlockPostgresDataHandlerSpec.scala +++ b/server/test/com/xsn/explorer/data/BlockPostgresDataHandlerSpec.scala @@ -54,6 +54,24 @@ class BlockPostgresDataHandlerSpec extends PostgresDataHandlerSpec { } } + "delete" should { + "delete a block" in { + val block = BlockLoader.get("1ca318b7a26ed67ca7c8c9b5069d653ba224bf86989125d1dfbb0973b7d6a5e0") + dataHandler.create(block) + + val result = dataHandler.delete(block.hash) + result.isGood mustEqual true + matches(block, result.get) + } + + "fail on block not found" in { + val blockhash = Blockhash.from("b858d38a3552c83aea58f66fe00ae220352a235e33fcf1f3af04507a61a9dc32").get + + val result = dataHandler.delete(blockhash) + result mustEqual Bad(BlockNotFoundError).accumulating + } + } + private def matches(expected: Block, result: Block) = { // NOTE: transactions and confirmations are not matched intentionally result.hash mustEqual expected.hash