From f111aabd98f01e0b6622af43df511aea01dd7e20 Mon Sep 17 00:00:00 2001 From: Jonathan Zernik Date: Sun, 21 Feb 2021 13:05:22 -0800 Subject: [PATCH] Use configurable retention for sent offer deletion (#865) --- squeaknode/config/config.py | 3 ++ squeaknode/db/squeak_db.py | 42 ++++++++++++++++++++++------ squeaknode/node/squeak_controller.py | 5 +++- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/squeaknode/config/config.py b/squeaknode/config/config.py index 48fc67fd..8ff442b5 100644 --- a/squeaknode/config/config.py +++ b/squeaknode/config/config.py @@ -37,6 +37,7 @@ DEFAULT_LND_HOST = "localhost" DEFAULT_SYNC_INTERVAL_S = 10 DEFAULT_SYNC_TIMEOUT_S = 10 DEFAULT_SYNC_BLOCK_INTERVAL = 2016 +DEFAULT_SENT_OFFER_RETENTION_S = 86400 @section('bitcoin') @@ -95,6 +96,8 @@ class CoreConfig(Config): cast=int, required=False, default=DEFAULT_MAX_SQUEAKS_PER_ADDRESS_PER_BLOCK) sqk_dir_path = key(cast=str, required=False, default=DEFAULT_SQK_DIR_PATH) log_level = key(cast=str, required=False, default=DEFAULT_LOG_LEVEL) + sent_offer_retention_s = key( + cast=int, required=False, default=DEFAULT_SENT_OFFER_RETENTION_S) @section('sync') diff --git a/squeaknode/db/squeak_db.py b/squeaknode/db/squeak_db.py index 82a013ef..8fd6e4da 100644 --- a/squeaknode/db/squeak_db.py +++ b/squeaknode/db/squeak_db.py @@ -110,28 +110,44 @@ class SqueakDb: return self.squeaks.c.created > \ self.datetime_now - timedelta(seconds=interval_s) - def received_offer_is_expired(self): + def received_offer_should_be_deleted(self): expire_time = ( self.received_offers.c.invoice_timestamp + self.received_offers.c.invoice_expiry ) - return self.datetime_now.timestamp() > expire_time + return self.datetime_now.timestamp() >= expire_time @property def received_offer_is_not_paid(self): return self.received_offers.c.paid == False # noqa: E711 - def sent_offer_is_expired(self): + @property + def received_offer_is_not_expired(self): + expire_time = ( + self.received_offers.c.invoice_timestamp + + self.received_offers.c.invoice_expiry + ) + return self.datetime_now.timestamp() < expire_time + + def sent_offer_should_be_deleted(self, interval_s): expire_time = ( self.sent_offers.c.invoice_timestamp + self.sent_offers.c.invoice_expiry ) - return self.datetime_now.timestamp() > expire_time + return self.datetime_now.timestamp() >= expire_time + interval_s @property def sent_offer_is_not_paid(self): return self.sent_offers.c.paid == False # noqa: E711 + @property + def sent_offer_is_not_expired(self): + expire_time = ( + self.sent_offers.c.invoice_timestamp + + self.sent_offers.c.invoice_expiry + ) + return self.datetime_now.timestamp() < expire_time + def insert_squeak(self, squeak: CSqueak, block_header: CBlockHeader) -> bytes: """ Insert a new squeak. TODO: Clear the decryption key from the serialized bytes @@ -686,6 +702,7 @@ class SqueakDb: ) .where(self.received_offers.c.squeak_hash == squeak_hash.hex()) .where(self.received_offer_is_not_paid) + .where(self.received_offer_is_not_expired) ) with self.get_connection() as connection: result = connection.execute(s) @@ -717,7 +734,7 @@ class SqueakDb: def delete_expired_received_offers(self): """ Delete all expired offers. """ s = self.received_offers.delete().where( - self.received_offer_is_expired() + self.received_offer_should_be_deleted() ) with self.get_connection() as connection: res = connection.execute(s) @@ -850,12 +867,16 @@ class SqueakDb: return sent_offer def get_sent_offer_by_squeak_hash_and_client_addr(self, squeak_hash: bytes, client_addr: str) -> Optional[SentOffer]: - """ Get a sent offer by squeak hash and client addr. """ + """ + Get a sent offer by squeak hash and client addr. Only + return sent offer if it's not expired and not paid. + """ s = ( select([self.sent_offers]) .where(self.sent_offers.c.squeak_hash == squeak_hash.hex()) .where(self.sent_offers.c.client_addr == client_addr) .where(self.sent_offer_is_not_paid) + .where(self.sent_offer_is_not_expired) ) with self.get_connection() as connection: result = connection.execute(s) @@ -873,10 +894,13 @@ class SqueakDb: with self.get_connection() as connection: connection.execute(s) - def delete_expired_sent_offers(self): - """ Delete all expired sent offers. """ + def delete_expired_sent_offers(self, interval_s): + """ + Delete all expired sent offers. Only delete sent + offers that have been expired for more than interval_s seconds. + """ s = self.sent_offers.delete().where( - self.sent_offer_is_expired() + self.sent_offer_should_be_deleted(interval_s) ) with self.get_connection() as connection: res = connection.execute(s) diff --git a/squeaknode/node/squeak_controller.py b/squeaknode/node/squeak_controller.py index dfff6d5c..928dab3c 100644 --- a/squeaknode/node/squeak_controller.py +++ b/squeaknode/node/squeak_controller.py @@ -411,7 +411,10 @@ class SqueakController: def delete_all_expired_sent_offers(self): logger.info("Deleting expired sent offers.") - num_expired_sent_offers = self.squeak_db.delete_expired_sent_offers() + sent_offer_retention_s = self.config.core.sent_offer_retention_s + num_expired_sent_offers = self.squeak_db.delete_expired_sent_offers( + sent_offer_retention_s, + ) if num_expired_sent_offers > 0: logger.info( "Deleted number of expired sent offers: {}".format(