From 6e54e9f870fdb73ad15cadde9d07cd22f24dbb49 Mon Sep 17 00:00:00 2001 From: Alexis Hernandez Date: Wed, 26 Dec 2018 22:41:32 -0700 Subject: [PATCH] server: Add keyset-based method for retrieving address transactions --- .../explorer/data/TransactionDataHandler.scala | 4 +++- .../anorm/TransactionPostgresDataHandler.scala | 7 ++++++- .../anorm/dao/TransactionPostgresDAO.scala | 18 +++++++++++++++++- .../async/TransactionFutureDataHandler.scala | 10 +++++++++- .../TransactionPostgresDataHandlerSpec.scala | 6 ++++++ .../helpers/TransactionDummyDataHandler.scala | 3 +++ 6 files changed, 44 insertions(+), 4 deletions(-) diff --git a/server/app/com/xsn/explorer/data/TransactionDataHandler.scala b/server/app/com/xsn/explorer/data/TransactionDataHandler.scala index 30896c3..9ecfc97 100644 --- a/server/app/com/xsn/explorer/data/TransactionDataHandler.scala +++ b/server/app/com/xsn/explorer/data/TransactionDataHandler.scala @@ -2,7 +2,7 @@ package com.xsn.explorer.data import com.alexitc.playsonify.core.ApplicationResult import com.alexitc.playsonify.models.ordering.FieldOrdering -import com.alexitc.playsonify.models.pagination.{PaginatedQuery, PaginatedResult} +import com.alexitc.playsonify.models.pagination.{Limit, PaginatedQuery, PaginatedResult} import com.xsn.explorer.models._ import com.xsn.explorer.models.fields.TransactionField import org.scalactic.Every @@ -16,6 +16,8 @@ trait TransactionDataHandler[F[_]] { paginatedQuery: PaginatedQuery, ordering: FieldOrdering[TransactionField]): F[PaginatedResult[TransactionWithValues]] + def getBy(address: Address, before: Long, limit: Limit): F[List[Transaction]] + def getUnspentOutputs(address: Address): F[List[Transaction.Output]] def getByBlockhash( diff --git a/server/app/com/xsn/explorer/data/anorm/TransactionPostgresDataHandler.scala b/server/app/com/xsn/explorer/data/anorm/TransactionPostgresDataHandler.scala index 373890d..cab58e7 100644 --- a/server/app/com/xsn/explorer/data/anorm/TransactionPostgresDataHandler.scala +++ b/server/app/com/xsn/explorer/data/anorm/TransactionPostgresDataHandler.scala @@ -2,7 +2,7 @@ package com.xsn.explorer.data.anorm import com.alexitc.playsonify.core.ApplicationResult import com.alexitc.playsonify.models.ordering.FieldOrdering -import com.alexitc.playsonify.models.pagination.{PaginatedQuery, PaginatedResult} +import com.alexitc.playsonify.models.pagination.{Limit, PaginatedQuery, PaginatedResult} import com.xsn.explorer.data.TransactionBlockingDataHandler import com.xsn.explorer.data.anorm.dao.TransactionPostgresDAO import com.xsn.explorer.models._ @@ -29,6 +29,11 @@ class TransactionPostgresDataHandler @Inject() ( Good(result) } + def getBy(address: Address, before: Long, limit: Limit): ApplicationResult[List[Transaction]] = withConnection { implicit conn => + val transactions = transactionPostgresDAO.getBy(address, before, limit) + Good(transactions) + } + override def getUnspentOutputs(address: Address): ApplicationResult[List[Transaction.Output]] = withConnection { implicit conn => val result = transactionPostgresDAO.getUnspentOutputs(address) Good(result) diff --git a/server/app/com/xsn/explorer/data/anorm/dao/TransactionPostgresDAO.scala b/server/app/com/xsn/explorer/data/anorm/dao/TransactionPostgresDAO.scala index d57748a..f6b66e8 100644 --- a/server/app/com/xsn/explorer/data/anorm/dao/TransactionPostgresDAO.scala +++ b/server/app/com/xsn/explorer/data/anorm/dao/TransactionPostgresDAO.scala @@ -4,7 +4,7 @@ import java.sql.Connection import anorm._ import com.alexitc.playsonify.models.ordering.FieldOrdering -import com.alexitc.playsonify.models.pagination.{Count, PaginatedQuery} +import com.alexitc.playsonify.models.pagination.{Count, Limit, PaginatedQuery} import com.alexitc.playsonify.sql.FieldOrderingSQLInterpreter import com.xsn.explorer.data.anorm.parsers.TransactionParsers._ import com.xsn.explorer.models._ @@ -88,6 +88,22 @@ class TransactionPostgresDAO @Inject() (fieldOrderingSQLInterpreter: FieldOrderi .getOrElse { throw new RuntimeException("Failed to delete transactions consistently")} // this should not happen } + def getBy(address: Address, before: Long, limit: Limit)(implicit conn: Connection): List[Transaction] = { + SQL( + """ + |SELECT t.txid, t.blockhash, t.time, t.size + |FROM transactions t JOIN address_transaction_details USING (txid) + |WHERE t.time < {before} AND address = {address} + |ORDER BY time DESC + |LIMIT {limit} + """.stripMargin + ).on( + 'address -> address.string, + 'limit -> limit.int, + 'before -> before + ).as(parseTransaction.*).flatten + } + def getBy( address: Address, paginatedQuery: PaginatedQuery, diff --git a/server/app/com/xsn/explorer/data/async/TransactionFutureDataHandler.scala b/server/app/com/xsn/explorer/data/async/TransactionFutureDataHandler.scala index 2654850..81bc2e3 100644 --- a/server/app/com/xsn/explorer/data/async/TransactionFutureDataHandler.scala +++ b/server/app/com/xsn/explorer/data/async/TransactionFutureDataHandler.scala @@ -2,7 +2,7 @@ package com.xsn.explorer.data.async import com.alexitc.playsonify.core.{FutureApplicationResult, FuturePaginatedResult} import com.alexitc.playsonify.models.ordering.FieldOrdering -import com.alexitc.playsonify.models.pagination.PaginatedQuery +import com.alexitc.playsonify.models.pagination.{Limit, PaginatedQuery} import com.xsn.explorer.data.{TransactionBlockingDataHandler, TransactionDataHandler} import com.xsn.explorer.executors.DatabaseExecutionContext import com.xsn.explorer.models._ @@ -25,6 +25,14 @@ class TransactionFutureDataHandler @Inject() ( blockingDataHandler.getBy(address, paginatedQuery, ordering) } + override def getBy( + address: Address, + before: Long, + limit: Limit): FutureApplicationResult[List[Transaction]] = Future { + + blockingDataHandler.getBy(address, before, limit) + } + override def getUnspentOutputs(address: Address): FutureApplicationResult[List[Transaction.Output]] = Future { blockingDataHandler.getUnspentOutputs(address) } diff --git a/server/test/com/xsn/explorer/data/TransactionPostgresDataHandlerSpec.scala b/server/test/com/xsn/explorer/data/TransactionPostgresDataHandlerSpec.scala index 53c6d9f..9e4fdd0 100644 --- a/server/test/com/xsn/explorer/data/TransactionPostgresDataHandlerSpec.scala +++ b/server/test/com/xsn/explorer/data/TransactionPostgresDataHandlerSpec.scala @@ -319,6 +319,12 @@ class TransactionPostgresDataHandlerSpec extends PostgresDataHandlerSpec with Be } } + "getBy keyset pagination" should { + "work" in { + pending + } + } + private def createBlock(block: Block) = { val transactions = block.transactions .map(_.string) diff --git a/server/test/com/xsn/explorer/helpers/TransactionDummyDataHandler.scala b/server/test/com/xsn/explorer/helpers/TransactionDummyDataHandler.scala index 3a5b0a4..c95a6b4 100644 --- a/server/test/com/xsn/explorer/helpers/TransactionDummyDataHandler.scala +++ b/server/test/com/xsn/explorer/helpers/TransactionDummyDataHandler.scala @@ -2,6 +2,7 @@ package com.xsn.explorer.helpers import com.alexitc.playsonify.core.ApplicationResult import com.alexitc.playsonify.models.ordering.FieldOrdering +import com.alexitc.playsonify.models.pagination import com.alexitc.playsonify.models.pagination.{PaginatedQuery, PaginatedResult} import com.xsn.explorer.data.TransactionBlockingDataHandler import com.xsn.explorer.models._ @@ -12,6 +13,8 @@ class TransactionDummyDataHandler extends TransactionBlockingDataHandler { override def getBy(address: Address, paginatedQuery: PaginatedQuery, ordering: FieldOrdering[TransactionField]): ApplicationResult[PaginatedResult[TransactionWithValues]] = ??? + override def getBy(address: Address, before: Long, limit: pagination.Limit): ApplicationResult[List[Transaction]] = ??? + override def getUnspentOutputs(address: Address): ApplicationResult[List[Transaction.Output]] = ??? override def getByBlockhash(blockhash: Blockhash, paginatedQuery: PaginatedQuery, ordering: FieldOrdering[TransactionField]): ApplicationResult[PaginatedResult[TransactionWithValues]] = ???