mirror of
https://github.com/ACINQ/eclair.git
synced 2025-02-20 13:34:35 +01:00
Remove close() in db interfaces (#2303)
* Remove close() in db interfaces It shouldn't be the responsibility of individual db classes to close the underlying db connection because they typically share the same db instance (postgres) or db files (sqlite). Closing should be handled in the `Databases` level (which is already the case for postgres. For sqlite, closing was only useful for mobile apps, which now use lightning-kmp. Also removed `DbFeeProvider`, which was only used by mobile apps. * increase github ci build time 20min->30min
This commit is contained in:
parent
ecbec93dfe
commit
e08353b243
26 changed files with 10 additions and 408 deletions
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
|
@ -10,7 +10,7 @@ jobs:
|
|||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Copyright 2020 ACINQ SAS
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package fr.acinq.eclair.blockchain.fee
|
||||
|
||||
import fr.acinq.eclair.db.FeeratesDb
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
|
||||
class DbFeeProvider(db: FeeratesDb, provider: FeeProvider)(implicit ec: ExecutionContext) extends FeeProvider {
|
||||
|
||||
/** This method retrieves feerates from the provider, and store results in the database */
|
||||
override def getFeerates: Future[FeeratesPerKB] =
|
||||
provider.getFeerates map { feerates =>
|
||||
db.addOrUpdateFeerates(feerates)
|
||||
feerates
|
||||
}
|
||||
|
||||
}
|
|
@ -18,15 +18,13 @@ package fr.acinq.eclair.db
|
|||
|
||||
import fr.acinq.bitcoin.scalacompat.Crypto.PublicKey
|
||||
import fr.acinq.bitcoin.scalacompat.{ByteVector32, Satoshi}
|
||||
import fr.acinq.eclair.{TimestampMilli, TimestampSecond}
|
||||
import fr.acinq.eclair.TimestampMilli
|
||||
import fr.acinq.eclair.channel._
|
||||
import fr.acinq.eclair.db.AuditDb.{NetworkFee, Stats}
|
||||
import fr.acinq.eclair.db.DbEventHandler.ChannelEvent
|
||||
import fr.acinq.eclair.payment.{PathFindingExperimentMetrics, PaymentReceived, PaymentRelayed, PaymentSent}
|
||||
|
||||
import java.io.Closeable
|
||||
|
||||
trait AuditDb extends Closeable {
|
||||
trait AuditDb {
|
||||
|
||||
def add(channelLifecycle: ChannelEvent): Unit
|
||||
|
||||
|
|
|
@ -21,9 +21,7 @@ import fr.acinq.eclair.CltvExpiry
|
|||
import fr.acinq.eclair.channel.PersistentChannelData
|
||||
import fr.acinq.eclair.db.DbEventHandler.ChannelEvent
|
||||
|
||||
import java.io.Closeable
|
||||
|
||||
trait ChannelsDb extends Closeable {
|
||||
trait ChannelsDb {
|
||||
|
||||
def addOrUpdateChannel(data: PersistentChannelData): Unit
|
||||
|
||||
|
|
|
@ -132,11 +132,6 @@ case class DualNetworkDb(primary: NetworkDb, secondary: NetworkDb) extends Netwo
|
|||
runAsync(secondary.isPruned(shortChannelId))
|
||||
primary.isPruned(shortChannelId)
|
||||
}
|
||||
|
||||
override def close(): Unit = {
|
||||
runAsync(secondary.close())
|
||||
primary.close()
|
||||
}
|
||||
}
|
||||
|
||||
case class DualAuditDb(primary: AuditDb, secondary: AuditDb) extends AuditDb {
|
||||
|
@ -212,11 +207,6 @@ case class DualAuditDb(primary: AuditDb, secondary: AuditDb) extends AuditDb {
|
|||
runAsync(secondary.stats(from, to))
|
||||
primary.stats(from, to)
|
||||
}
|
||||
|
||||
override def close(): Unit = {
|
||||
runAsync(secondary.close())
|
||||
primary.close()
|
||||
}
|
||||
}
|
||||
|
||||
case class DualChannelsDb(primary: ChannelsDb, secondary: ChannelsDb) extends ChannelsDb {
|
||||
|
@ -257,11 +247,6 @@ case class DualChannelsDb(primary: ChannelsDb, secondary: ChannelsDb) extends Ch
|
|||
runAsync(secondary.listHtlcInfos(channelId, commitmentNumber))
|
||||
primary.listHtlcInfos(channelId, commitmentNumber)
|
||||
}
|
||||
|
||||
override def close(): Unit = {
|
||||
runAsync(secondary.close())
|
||||
primary.close()
|
||||
}
|
||||
}
|
||||
|
||||
case class DualPeersDb(primary: PeersDb, secondary: PeersDb) extends PeersDb {
|
||||
|
@ -297,11 +282,6 @@ case class DualPeersDb(primary: PeersDb, secondary: PeersDb) extends PeersDb {
|
|||
runAsync(secondary.getRelayFees(nodeId))
|
||||
primary.getRelayFees(nodeId)
|
||||
}
|
||||
|
||||
override def close(): Unit = {
|
||||
runAsync(secondary.close())
|
||||
primary.close()
|
||||
}
|
||||
}
|
||||
|
||||
case class DualPaymentsDb(primary: PaymentsDb, secondary: PaymentsDb) extends PaymentsDb {
|
||||
|
@ -313,11 +293,6 @@ case class DualPaymentsDb(primary: PaymentsDb, secondary: PaymentsDb) extends Pa
|
|||
primary.listPaymentsOverview(limit)
|
||||
}
|
||||
|
||||
override def close(): Unit = {
|
||||
runAsync(secondary.close())
|
||||
primary.close()
|
||||
}
|
||||
|
||||
override def addIncomingPayment(pr: Bolt11Invoice, preimage: ByteVector32, paymentType: String): Unit = {
|
||||
runAsync(secondary.addIncomingPayment(pr, preimage, paymentType))
|
||||
primary.addIncomingPayment(pr, preimage, paymentType)
|
||||
|
@ -392,7 +367,6 @@ case class DualPaymentsDb(primary: PaymentsDb, secondary: PaymentsDb) extends Pa
|
|||
runAsync(secondary.listOutgoingPayments(from, to))
|
||||
primary.listOutgoingPayments(from, to)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
case class DualPendingCommandsDb(primary: PendingCommandsDb, secondary: PendingCommandsDb) extends PendingCommandsDb {
|
||||
|
@ -418,9 +392,4 @@ case class DualPendingCommandsDb(primary: PendingCommandsDb, secondary: PendingC
|
|||
runAsync(secondary.listSettlementCommands())
|
||||
primary.listSettlementCommands()
|
||||
}
|
||||
|
||||
override def close(): Unit = {
|
||||
runAsync(secondary.close())
|
||||
primary.close()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Copyright 2020 ACINQ SAS
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package fr.acinq.eclair.db
|
||||
|
||||
import fr.acinq.eclair.blockchain.fee.FeeratesPerKB
|
||||
|
||||
import java.io.Closeable
|
||||
|
||||
/**
|
||||
* This database stores the fee rates retrieved by a [[fr.acinq.eclair.blockchain.fee.FeeProvider]].
|
||||
*/
|
||||
trait FeeratesDb extends Closeable {
|
||||
|
||||
/** Insert or update the feerates into the feerates database. */
|
||||
def addOrUpdateFeerates(feeratesPerKB: FeeratesPerKB): Unit
|
||||
|
||||
/** Return the (optional) feerates from the feerates database. */
|
||||
def getFeerates(): Option[FeeratesPerKB]
|
||||
|
||||
}
|
|
@ -22,10 +22,9 @@ import fr.acinq.eclair.ShortChannelId
|
|||
import fr.acinq.eclair.router.Router.PublicChannel
|
||||
import fr.acinq.eclair.wire.protocol.{ChannelAnnouncement, ChannelUpdate, NodeAnnouncement}
|
||||
|
||||
import java.io.Closeable
|
||||
import scala.collection.immutable.SortedMap
|
||||
|
||||
trait NetworkDb extends Closeable {
|
||||
trait NetworkDb {
|
||||
|
||||
def addNode(n: NodeAnnouncement): Unit
|
||||
|
||||
|
|
|
@ -22,11 +22,10 @@ import fr.acinq.eclair.payment._
|
|||
import fr.acinq.eclair.router.Router.{ChannelHop, Hop, NodeHop}
|
||||
import fr.acinq.eclair.{MilliSatoshi, ShortChannelId, TimestampMilli}
|
||||
|
||||
import java.io.Closeable
|
||||
import java.util.UUID
|
||||
import scala.util.Try
|
||||
|
||||
trait PaymentsDb extends IncomingPaymentsDb with OutgoingPaymentsDb with PaymentsOverviewDb with Closeable
|
||||
trait PaymentsDb extends IncomingPaymentsDb with OutgoingPaymentsDb with PaymentsOverviewDb
|
||||
|
||||
trait IncomingPaymentsDb {
|
||||
|
||||
|
|
|
@ -20,9 +20,7 @@ import fr.acinq.bitcoin.scalacompat.Crypto.PublicKey
|
|||
import fr.acinq.eclair.payment.relay.Relayer.RelayFees
|
||||
import fr.acinq.eclair.wire.protocol.NodeAddress
|
||||
|
||||
import java.io.Closeable
|
||||
|
||||
trait PeersDb extends Closeable {
|
||||
trait PeersDb {
|
||||
|
||||
def addOrUpdatePeer(nodeId: PublicKey, address: NodeAddress): Unit
|
||||
|
||||
|
|
|
@ -22,8 +22,6 @@ import fr.acinq.bitcoin.scalacompat.ByteVector32
|
|||
import fr.acinq.eclair.channel._
|
||||
import fr.acinq.eclair.wire.protocol.{UpdateFailHtlc, UpdateFailMalformedHtlc, UpdateFulfillHtlc, UpdateMessage}
|
||||
|
||||
import java.io.Closeable
|
||||
|
||||
/**
|
||||
* This database stores CMD_FULFILL_HTLC and CMD_FAIL_HTLC that we have received from downstream
|
||||
* (either directly via UpdateFulfillHtlc or by extracting the value from the
|
||||
|
@ -36,7 +34,7 @@ import java.io.Closeable
|
|||
* to handle all corner cases.
|
||||
*
|
||||
*/
|
||||
trait PendingCommandsDb extends Closeable {
|
||||
trait PendingCommandsDb {
|
||||
|
||||
def addSettlementCommand(channelId: ByteVector32, cmd: HtlcSettlementCommand): Unit
|
||||
|
||||
|
|
|
@ -474,7 +474,4 @@ class PgAuditDb(implicit ds: DataSource) extends AuditDb with Logging {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
override def close(): Unit = ()
|
||||
|
||||
}
|
||||
|
|
|
@ -252,6 +252,4 @@ class PgChannelsDb(implicit ds: DataSource, lock: PgLock) extends ChannelsDb wit
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def close(): Unit = ()
|
||||
}
|
||||
|
|
|
@ -267,6 +267,4 @@ class PgNetworkDb(implicit ds: DataSource) extends NetworkDb with Logging {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def close(): Unit = ()
|
||||
}
|
||||
|
|
|
@ -406,7 +406,4 @@ class PgPaymentsDb(implicit ds: DataSource, lock: PgLock) extends PaymentsDb wit
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def close(): Unit = ()
|
||||
|
||||
}
|
|
@ -155,6 +155,4 @@ class PgPeersDb(implicit ds: DataSource, lock: PgLock) extends PeersDb with Logg
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def close(): Unit = ()
|
||||
}
|
||||
|
|
|
@ -113,6 +113,4 @@ class PgPendingCommandsDb(implicit ds: DataSource, lock: PgLock) extends Pending
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def close(): Unit = ()
|
||||
}
|
||||
|
|
|
@ -460,8 +460,4 @@ class SqliteAuditDb(val sqlite: Connection) extends AuditDb with Logging {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
// used by mobile apps
|
||||
override def close(): Unit = sqlite.close()
|
||||
|
||||
}
|
||||
|
|
|
@ -188,7 +188,4 @@ class SqliteChannelsDb(val sqlite: Connection) extends ChannelsDb with Logging {
|
|||
.toSeq
|
||||
}
|
||||
}
|
||||
|
||||
// used by mobile apps
|
||||
override def close(): Unit = sqlite.close()
|
||||
}
|
||||
|
|
|
@ -1,118 +0,0 @@
|
|||
/*
|
||||
* Copyright 2020 ACINQ SAS
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package fr.acinq.eclair.db.sqlite
|
||||
|
||||
import fr.acinq.bitcoin.scalacompat.Satoshi
|
||||
import fr.acinq.eclair.TimestampMilli
|
||||
import fr.acinq.eclair.blockchain.fee.{FeeratePerKB, FeeratesPerKB}
|
||||
import fr.acinq.eclair.db.FeeratesDb
|
||||
import grizzled.slf4j.Logging
|
||||
|
||||
import java.sql.{Connection, Statement}
|
||||
|
||||
object SqliteFeeratesDb {
|
||||
val DB_NAME = "feerates"
|
||||
val CURRENT_VERSION = 2
|
||||
}
|
||||
|
||||
class SqliteFeeratesDb(sqlite: Connection) extends FeeratesDb with Logging {
|
||||
|
||||
import SqliteFeeratesDb._
|
||||
import SqliteUtils.ExtendedResultSet._
|
||||
import SqliteUtils._
|
||||
|
||||
using(sqlite.createStatement(), inTransaction = true) { statement =>
|
||||
|
||||
def migration12(statement: Statement): Unit = {
|
||||
statement.executeUpdate("ALTER TABLE feerates_per_kb RENAME TO _feerates_per_kb_old")
|
||||
statement.executeUpdate(
|
||||
"""
|
||||
|CREATE TABLE feerates_per_kb (
|
||||
|rate_block_1 INTEGER NOT NULL, rate_blocks_2 INTEGER NOT NULL, rate_blocks_6 INTEGER NOT NULL, rate_blocks_12 INTEGER NOT NULL, rate_blocks_36 INTEGER NOT NULL, rate_blocks_72 INTEGER NOT NULL, rate_blocks_144 INTEGER NOT NULL, rate_blocks_1008 INTEGER NOT NULL,
|
||||
|timestamp INTEGER NOT NULL)""".stripMargin)
|
||||
statement.executeUpdate("INSERT INTO feerates_per_kb (rate_block_1, rate_blocks_2, rate_blocks_6, rate_blocks_12, rate_blocks_36, rate_blocks_72, rate_blocks_144, rate_blocks_1008, timestamp) SELECT rate_block_1, rate_blocks_2, rate_blocks_6, rate_blocks_12, rate_blocks_36, rate_blocks_72, rate_blocks_144, rate_blocks_144, timestamp FROM _feerates_per_kb_old")
|
||||
statement.executeUpdate("DROP table _feerates_per_kb_old")
|
||||
}
|
||||
|
||||
getVersion(statement, DB_NAME) match {
|
||||
case None =>
|
||||
// Create feerates table. Rates are in kb.
|
||||
statement.executeUpdate(
|
||||
"""
|
||||
|CREATE TABLE feerates_per_kb (
|
||||
|rate_block_1 INTEGER NOT NULL, rate_blocks_2 INTEGER NOT NULL, rate_blocks_6 INTEGER NOT NULL, rate_blocks_12 INTEGER NOT NULL, rate_blocks_36 INTEGER NOT NULL, rate_blocks_72 INTEGER NOT NULL, rate_blocks_144 INTEGER NOT NULL, rate_blocks_1008 INTEGER NOT NULL,
|
||||
|timestamp INTEGER NOT NULL)""".stripMargin)
|
||||
case Some(v@1) =>
|
||||
logger.warn(s"migrating db $DB_NAME, found version=$v current=$CURRENT_VERSION")
|
||||
migration12(statement)
|
||||
case Some(CURRENT_VERSION) => () // table is up-to-date, nothing to do
|
||||
case Some(unknownVersion) => throw new RuntimeException(s"Unknown version of DB $DB_NAME found, version=$unknownVersion")
|
||||
}
|
||||
setVersion(statement, DB_NAME, CURRENT_VERSION)
|
||||
}
|
||||
|
||||
override def addOrUpdateFeerates(feeratesPerKB: FeeratesPerKB): Unit = {
|
||||
using(sqlite.prepareStatement("UPDATE feerates_per_kb SET rate_block_1=?, rate_blocks_2=?, rate_blocks_6=?, rate_blocks_12=?, rate_blocks_36=?, rate_blocks_72=?, rate_blocks_144=?, rate_blocks_1008=?, timestamp=?")) { update =>
|
||||
update.setLong(1, feeratesPerKB.block_1.toLong)
|
||||
update.setLong(2, feeratesPerKB.blocks_2.toLong)
|
||||
update.setLong(3, feeratesPerKB.blocks_6.toLong)
|
||||
update.setLong(4, feeratesPerKB.blocks_12.toLong)
|
||||
update.setLong(5, feeratesPerKB.blocks_36.toLong)
|
||||
update.setLong(6, feeratesPerKB.blocks_72.toLong)
|
||||
update.setLong(7, feeratesPerKB.blocks_144.toLong)
|
||||
update.setLong(8, feeratesPerKB.blocks_1008.toLong)
|
||||
update.setLong(9, TimestampMilli.now().toLong)
|
||||
if (update.executeUpdate() == 0) {
|
||||
using(sqlite.prepareStatement("INSERT INTO feerates_per_kb VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)")) { insert =>
|
||||
insert.setLong(1, feeratesPerKB.block_1.toLong)
|
||||
insert.setLong(2, feeratesPerKB.blocks_2.toLong)
|
||||
insert.setLong(3, feeratesPerKB.blocks_6.toLong)
|
||||
insert.setLong(4, feeratesPerKB.blocks_12.toLong)
|
||||
insert.setLong(5, feeratesPerKB.blocks_36.toLong)
|
||||
insert.setLong(6, feeratesPerKB.blocks_72.toLong)
|
||||
insert.setLong(7, feeratesPerKB.blocks_144.toLong)
|
||||
insert.setLong(8, feeratesPerKB.blocks_1008.toLong)
|
||||
insert.setLong(9, TimestampMilli.now().toLong)
|
||||
insert.executeUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def getFeerates(): Option[FeeratesPerKB] = {
|
||||
using(sqlite.prepareStatement("SELECT rate_block_1, rate_blocks_2, rate_blocks_6, rate_blocks_12, rate_blocks_36, rate_blocks_72, rate_blocks_144, rate_blocks_1008 FROM feerates_per_kb")) { statement =>
|
||||
statement.executeQuery()
|
||||
.map { rs =>
|
||||
FeeratesPerKB(
|
||||
// NB: we don't bother storing this value in the DB, because it's unused on mobile.
|
||||
mempoolMinFee = FeeratePerKB(Satoshi(rs.getLong("rate_blocks_1008"))),
|
||||
block_1 = FeeratePerKB(Satoshi(rs.getLong("rate_block_1"))),
|
||||
blocks_2 = FeeratePerKB(Satoshi(rs.getLong("rate_blocks_2"))),
|
||||
blocks_6 = FeeratePerKB(Satoshi(rs.getLong("rate_blocks_6"))),
|
||||
blocks_12 = FeeratePerKB(Satoshi(rs.getLong("rate_blocks_12"))),
|
||||
blocks_36 = FeeratePerKB(Satoshi(rs.getLong("rate_blocks_36"))),
|
||||
blocks_72 = FeeratePerKB(Satoshi(rs.getLong("rate_blocks_72"))),
|
||||
blocks_144 = FeeratePerKB(Satoshi(rs.getLong("rate_blocks_144"))),
|
||||
blocks_1008 = FeeratePerKB(Satoshi(rs.getLong("rate_blocks_1008"))))
|
||||
}
|
||||
.headOption
|
||||
}
|
||||
}
|
||||
|
||||
// used by mobile apps
|
||||
override def close(): Unit = sqlite.close()
|
||||
}
|
|
@ -176,7 +176,4 @@ class SqliteNetworkDb(val sqlite: Connection) extends NetworkDb with Logging {
|
|||
statement.executeQuery().nonEmpty
|
||||
}
|
||||
}
|
||||
|
||||
// used by mobile apps
|
||||
override def close(): Unit = sqlite.close()
|
||||
}
|
||||
|
|
|
@ -396,10 +396,6 @@ class SqlitePaymentsDb(val sqlite: Connection) extends PaymentsDb with Logging {
|
|||
}.toSeq
|
||||
}
|
||||
}
|
||||
|
||||
// used by mobile apps
|
||||
override def close(): Unit = sqlite.close()
|
||||
|
||||
}
|
||||
|
||||
object SqlitePaymentsDb {
|
||||
|
|
|
@ -128,8 +128,4 @@ class SqlitePeersDb(val sqlite: Connection) extends PeersDb with Logging {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// used by mobile apps
|
||||
override def close(): Unit = sqlite.close()
|
||||
}
|
||||
|
|
|
@ -88,7 +88,4 @@ class SqlitePendingCommandsDb(val sqlite: Connection) extends PendingCommandsDb
|
|||
.toSeq
|
||||
}
|
||||
}
|
||||
|
||||
// used by mobile apps
|
||||
override def close(): Unit = sqlite.close()
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Copyright 2020 ACINQ SAS
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package fr.acinq.eclair.blockchain.fee
|
||||
|
||||
import akka.util.Timeout
|
||||
import fr.acinq.bitcoin.scalacompat.SatoshiLong
|
||||
import fr.acinq.eclair.TestDatabases
|
||||
import fr.acinq.eclair.db.sqlite.SqliteFeeratesDb
|
||||
import org.scalatest.funsuite.AnyFunSuite
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
import scala.concurrent.duration._
|
||||
|
||||
class DbFeeProviderSpec extends AnyFunSuite {
|
||||
|
||||
val feerates1: FeeratesPerKB = FeeratesPerKB(FeeratePerKB(800 sat), FeeratePerKB(100 sat), FeeratePerKB(200 sat), FeeratePerKB(300 sat), FeeratePerKB(400 sat), FeeratePerKB(500 sat), FeeratePerKB(600 sat), FeeratePerKB(700 sat), FeeratePerKB(800 sat))
|
||||
|
||||
test("db fee provider saves feerates in database") {
|
||||
val sqlite = TestDatabases.sqliteInMemory()
|
||||
val db = new SqliteFeeratesDb(sqlite)
|
||||
val provider = new DbFeeProvider(db, new ConstantFeeProvider(feerates1))
|
||||
|
||||
assert(db.getFeerates().isEmpty)
|
||||
assert(Await.result(provider.getFeerates, Timeout(30 seconds).duration) == feerates1)
|
||||
assert(db.getFeerates().get == feerates1)
|
||||
}
|
||||
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
* Copyright 2020 ACINQ SAS
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package fr.acinq.eclair.db
|
||||
|
||||
import fr.acinq.bitcoin.scalacompat.SatoshiLong
|
||||
import fr.acinq.eclair._
|
||||
import fr.acinq.eclair.blockchain.fee.{FeeratePerKB, FeeratesPerKB}
|
||||
import fr.acinq.eclair.db.pg.PgUtils.setVersion
|
||||
import fr.acinq.eclair.db.sqlite.SqliteFeeratesDb
|
||||
import fr.acinq.eclair.db.sqlite.SqliteUtils.{getVersion, using}
|
||||
import org.scalatest.funsuite.AnyFunSuite
|
||||
|
||||
class SqliteFeeratesDbSpec extends AnyFunSuite {
|
||||
|
||||
val feerate: FeeratesPerKB = FeeratesPerKB(
|
||||
mempoolMinFee = FeeratePerKB(10000 sat),
|
||||
block_1 = FeeratePerKB(150000 sat),
|
||||
blocks_2 = FeeratePerKB(120000 sat),
|
||||
blocks_6 = FeeratePerKB(100000 sat),
|
||||
blocks_12 = FeeratePerKB(90000 sat),
|
||||
blocks_36 = FeeratePerKB(70000 sat),
|
||||
blocks_72 = FeeratePerKB(50000 sat),
|
||||
blocks_144 = FeeratePerKB(20000 sat),
|
||||
blocks_1008 = FeeratePerKB(10000 sat))
|
||||
|
||||
test("init database 2 times in a row") {
|
||||
val sqlite = TestDatabases.sqliteInMemory()
|
||||
val db1 = new SqliteFeeratesDb(sqlite)
|
||||
val db2 = new SqliteFeeratesDb(sqlite)
|
||||
}
|
||||
|
||||
test("add/get feerates") {
|
||||
val sqlite = TestDatabases.sqliteInMemory()
|
||||
val db = new SqliteFeeratesDb(sqlite)
|
||||
|
||||
db.addOrUpdateFeerates(feerate)
|
||||
assert(db.getFeerates().get == feerate)
|
||||
}
|
||||
|
||||
test("migration v1 -> current") {
|
||||
val sqlite = TestDatabases.sqliteInMemory()
|
||||
|
||||
using(sqlite.createStatement()) { statement =>
|
||||
statement.executeUpdate(
|
||||
"""
|
||||
|CREATE TABLE IF NOT EXISTS feerates_per_kb (
|
||||
|rate_block_1 INTEGER NOT NULL, rate_blocks_2 INTEGER NOT NULL, rate_blocks_6 INTEGER NOT NULL, rate_blocks_12 INTEGER NOT NULL, rate_blocks_36 INTEGER NOT NULL, rate_blocks_72 INTEGER NOT NULL, rate_blocks_144 INTEGER NOT NULL,
|
||||
|timestamp INTEGER NOT NULL)""".stripMargin)
|
||||
setVersion(statement, "feerates", 1)
|
||||
}
|
||||
|
||||
using(sqlite.createStatement()) { statement =>
|
||||
assert(getVersion(statement, "feerates").contains(1))
|
||||
}
|
||||
|
||||
// Version 1 was missing the 1008 block target.
|
||||
using(sqlite.prepareStatement("INSERT INTO feerates_per_kb VALUES (?, ?, ?, ?, ?, ?, ?, ?)")) { statement =>
|
||||
statement.setLong(1, feerate.block_1.toLong)
|
||||
statement.setLong(2, feerate.blocks_2.toLong)
|
||||
statement.setLong(3, feerate.blocks_6.toLong)
|
||||
statement.setLong(4, feerate.blocks_12.toLong)
|
||||
statement.setLong(5, feerate.blocks_36.toLong)
|
||||
statement.setLong(6, feerate.blocks_72.toLong)
|
||||
statement.setLong(7, feerate.blocks_144.toLong)
|
||||
statement.setLong(8, TimestampMilli.now().toLong)
|
||||
statement.executeUpdate()
|
||||
}
|
||||
|
||||
val migratedDb = new SqliteFeeratesDb(sqlite)
|
||||
using(sqlite.createStatement()) { statement =>
|
||||
assert(getVersion(statement, "feerates").contains(SqliteFeeratesDb.CURRENT_VERSION))
|
||||
}
|
||||
|
||||
// When migrating, we simply copy the estimate for blocks 144 to blocks 1008.
|
||||
assert(migratedDb.getFeerates() == Some(feerate.copy(blocks_1008 = feerate.blocks_144, mempoolMinFee = feerate.blocks_144)))
|
||||
migratedDb.addOrUpdateFeerates(feerate)
|
||||
assert(migratedDb.getFeerates() == Some(feerate))
|
||||
}
|
||||
|
||||
}
|
|
@ -86,13 +86,13 @@ class SqliteUtilsSpec extends AnyFunSuite {
|
|||
|
||||
// first start : write to file
|
||||
val db1 = Databases.sqlite(datadir, Some(jdbcUrlPath))
|
||||
db1.channels.close()
|
||||
db1.channels.sqlite.close()
|
||||
|
||||
assert(Files.readString(jdbcUrlPath.toPath).trim == "sqlite")
|
||||
|
||||
// 2nd start : no-op
|
||||
val db2 = Databases.sqlite(datadir, Some(jdbcUrlPath))
|
||||
db2.channels.close()
|
||||
db2.channels.sqlite.close()
|
||||
|
||||
// we modify the file
|
||||
Files.writeString(jdbcUrlPath.toPath, "postgres")
|
||||
|
|
Loading…
Add table
Reference in a new issue