libeufin

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

gc.rs (2605B)


      1 /*
      2 * This file is part of LibEuFin.
      3 * Copyright (C) 2026 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 //! Data access logic for garbage collection
     21 
     22 use jiff::Timestamp;
     23 use sqlx::PgPool;
     24 use taler_api::db::BindHelper;
     25 
     26 /** Run garbage collection */
     27 pub async fn collect(
     28     db: &PgPool,
     29     abort_before: &Timestamp,
     30     clean_before: &Timestamp,
     31     delete_before: &Timestamp,
     32 ) -> sqlx::Result<()> {
     33     // Abort pending operations
     34     sqlx::query(
     35         "
     36             UPDATE taler_withdrawal_operations SET aborted = true WHERE creation_date < $1 AND NOT confirmation_done AND NOT EXISTS(
     37                 SELECT FROM prepared_transfers WHERE prepared_transfers.withdrawal_id=taler_withdrawal_operations.withdrawal_id
     38             )
     39         "
     40     ).bind_timestamp(abort_before).execute(db).await?;
     41 
     42     // Clean aborted operations, expired challenges and expired tokens
     43     for stm in [
     44         "DELETE FROM taler_withdrawal_operations WHERE aborted = true AND creation_date < $1 AND NOT EXISTS(
     45             SELECT FROM prepared_transfers WHERE prepared_transfers.withdrawal_id=taler_withdrawal_operations.withdrawal_id
     46         )",
     47         "DELETE FROM tan_challenges WHERE expiration_date < $1",
     48         "DELETE FROM bearer_tokens WHERE expiration_time < $1"
     49     ] {
     50         sqlx::query(stm).bind_timestamp(clean_before).execute(db).await?;
     51     }
     52 
     53     // Delete old bank transactions, linked operations are deleted by CASCADE
     54     sqlx::query("DELETE FROM bank_account_transactions WHERE transaction_date < $1")
     55         .bind_timestamp(delete_before)
     56         .execute(db)
     57         .await?;
     58 
     59     // Hard delete soft deleted customer without bank transactions, bank account are deleted by CASCADE
     60     sqlx::query(
     61         "DELETE FROM customers WHERE deleted_at IS NOT NULL AND NOT EXISTS(
     62           SELECT FROM bank_account_transactions NATURAL JOIN bank_accounts
     63               WHERE owning_customer_id=customer_id
     64       )",
     65     )
     66     .execute(db)
     67     .await?;
     68 
     69     Ok(())
     70 }