libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

GcDAO.kt (2877B)


      1 /*
      2  * This file is part of LibEuFin.
      3  * Copyright (C) 2024-2025 Taler Systems S.A.
      4 
      5  * LibEuFin is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU Affero General Public License as
      7  * published by the Free Software Foundation; either version 3, or
      8  * (at your option) any later version.
      9 
     10  * LibEuFin is distributed in the hope that it will be useful, but
     11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
     13  * Public License for more details.
     14 
     15  * You should have received a copy of the GNU Affero General Public
     16  * License along with LibEuFin; see the file COPYING.  If not, see
     17  * <http://www.gnu.org/licenses/>
     18  */
     19 
     20 package tech.libeufin.bank.db
     21 
     22 import tech.libeufin.common.db.withStatement
     23 import tech.libeufin.common.micros
     24 import java.time.Duration
     25 import java.time.Instant
     26 
     27 /** Data access logic for garbage collection */
     28 class GcDAO(private val db: Database) {
     29     /** Run garbage collection  */
     30     suspend fun collect(
     31         timestamp: Instant,
     32         abortAfter: Duration,
     33         cleanAfter: Duration,
     34         deleteAfter: Duration
     35     ) = db.conn { conn ->
     36         val abortAfterMicro = timestamp.minus(abortAfter).micros()
     37         val cleanAfterMicro = timestamp.minus(cleanAfter).micros()
     38         val deleteAfterMicro = timestamp.minus(deleteAfter).micros()
     39         
     40         // Abort pending operations
     41         conn.withStatement(
     42             "UPDATE taler_withdrawal_operations SET aborted = true WHERE creation_date < ?"
     43         ) {
     44             bind(abortAfterMicro) 
     45             executeUpdate()
     46         }
     47 
     48         // Clean aborted operations, expired challenges and expired tokens
     49         for (smt in listOf(
     50             "DELETE FROM taler_withdrawal_operations WHERE aborted = true AND creation_date < ?",
     51             "DELETE FROM tan_challenges WHERE expiration_date < ?",
     52             "DELETE FROM bearer_tokens WHERE expiration_time < ?"
     53         )) {
     54             conn.withStatement(smt) {
     55                 bind(cleanAfterMicro) 
     56                 executeUpdate()
     57             }
     58         }
     59 
     60         // Delete old bank transactions, linked operations are deleted by CASCADE
     61         conn.withStatement(
     62             "DELETE FROM bank_account_transactions WHERE transaction_date < ?"
     63         ) {
     64             bind(deleteAfterMicro) 
     65             executeUpdate()
     66         }
     67 
     68         // Hard delete soft deleted customer without bank transactions, bank account are deleted by CASCADE
     69         conn.withStatement("""
     70             DELETE FROM customers WHERE deleted_at IS NOT NULL AND NOT EXISTS(
     71                 SELECT 1 FROM bank_account_transactions NATURAL JOIN bank_accounts
     72                     WHERE owning_customer_id=customer_id
     73             )
     74         """) {
     75             executeUpdate()
     76         }
     77 
     78         // TODO clean stats
     79     }
     80 }