From 3330bb4203b1419b235f6b7b284a0e5dc431f270 Mon Sep 17 00:00:00 2001 From: "r.perez" Date: Tue, 21 Jul 2026 19:53:10 -0400 Subject: [PATCH 1/5] [IMP] auto_backup_fs_file: hide folder for fs_file; add folder constrains --- auto_backup_fs_file/models/db_backup.py | 11 +++++++++++ auto_backup_fs_file/views/db_backup_views.xml | 9 ++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/auto_backup_fs_file/models/db_backup.py b/auto_backup_fs_file/models/db_backup.py index 7e1411e80bd..42d0ae6d339 100644 --- a/auto_backup_fs_file/models/db_backup.py +++ b/auto_backup_fs_file/models/db_backup.py @@ -27,6 +27,17 @@ class DbBackup(models.Model): responsible_id = fields.Many2one("res.users", help="User to be notified.") + folder = fields.Char(required=False, default=False) + + @api.constrains("method", "folder") + def _check_folder_required_for_method(self): + """folder is only required for local and sftp methods, not fs_file.""" + for record in self: + if record.method and record.method != "fs_file" and not record.folder: + raise ValidationError( + _("Folder is required for local and SFTP backup methods.") + ) + @api.model def _get_fs_storage(self): """Get the fs_storage to be used for fs_file backups.""" diff --git a/auto_backup_fs_file/views/db_backup_views.xml b/auto_backup_fs_file/views/db_backup_views.xml index 1bbe336b90e..852ebef25f6 100644 --- a/auto_backup_fs_file/views/db_backup_views.xml +++ b/auto_backup_fs_file/views/db_backup_views.xml @@ -16,16 +16,19 @@ type="object" icon="fa-archive" > - - + + + method == 'fs_file' + - + From 5245ab009670c8433a014947633cf84aa6bcf3a3 Mon Sep 17 00:00:00 2001 From: "r.perez" Date: Tue, 21 Jul 2026 19:54:29 -0400 Subject: [PATCH 2/5] [IMP] auto_backup_fs_file: add @api.depends to is_expired; explicit unlink for GC --- .../models/db_backup_fs_file.py | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/auto_backup_fs_file/models/db_backup_fs_file.py b/auto_backup_fs_file/models/db_backup_fs_file.py index 4934b400845..d5f5fabfefa 100644 --- a/auto_backup_fs_file/models/db_backup_fs_file.py +++ b/auto_backup_fs_file/models/db_backup_fs_file.py @@ -22,6 +22,7 @@ class DbBackupFsFile(models.Model): help="Indicates whether the backup has exceeded its storage time.", ) + @api.depends("db_backup_id.days_to_keep", "create_date") def _compute_is_expired(self): """Compute whether the backup has exceeded its storage time.""" for record in self: @@ -34,6 +35,25 @@ def _compute_is_expired(self): else: record.is_expired = False + def unlink(self): + """Unlink backing ir.attachment records before deleting the DB record. + + Odoo's base Model.unlink() does cascade-delete ir.attachment via raw + SQL, but we make this explicit to ensure the fs_attachment GC stack + (_fs_mark_for_gc) is triggered reliably. The physical file on the + external storage is removed by the autovacuum GC job + (fs_file_gc._gc_files), not synchronously here. + """ + attachments = self.env["ir.attachment"].search( + [ + ("res_model", "=", self._name), + ("res_id", "in", self.ids), + ("res_field", "=", "backup_file"), + ] + ) + attachments.unlink() + return super().unlink() + @api.model def fs_storage(self): FsStorage = self.env["fs.storage"] @@ -51,7 +71,3 @@ def fs_storage(self): if fs_storage: return fs_storage return False - - def get_fs_storage_filename(self): - self.ensure_one() - return self.backup_file.attachment.store_fname.split("://")[-1] From 27d8f0057462025677a56a30c05dddcf29df48c3 Mon Sep 17 00:00:00 2001 From: "r.perez" Date: Tue, 21 Jul 2026 19:55:56 -0400 Subject: [PATCH 3/5] [IMP] auto_backup_fs_file: delegate cleanup to GC; trigger cleanup from action_backup --- auto_backup_fs_file/models/db_backup.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/auto_backup_fs_file/models/db_backup.py b/auto_backup_fs_file/models/db_backup.py index 42d0ae6d339..f7290c04d95 100644 --- a/auto_backup_fs_file/models/db_backup.py +++ b/auto_backup_fs_file/models/db_backup.py @@ -74,6 +74,7 @@ def _check_fs_file_backup_storage(self): def action_backup(self): """Override the action_backup method to add the fs_file method.""" fs_backups = self.filtered(lambda it: it.method == "fs_file") + successful_fs = self.browse() dbname = self.env.cr.dbname for fs_backup in fs_backups: with fs_backup.backup_log(): @@ -114,7 +115,9 @@ def action_backup(self): summary=_("Database backup is ready to download."), user_id=user_to_notify.id, ) + successful_fs |= fs_backup res = super().action_backup() + successful_fs.cleanup() return res def action_open_fs_backups_view(self): @@ -126,14 +129,18 @@ def action_open_fs_backups_view(self): return action def cleanup(self): - """Extend cleanup to fs_file backups.""" + """Extend cleanup to fs_file backups. + + Physical file removal is handled by the fs_attachment GC stack: + unlink() on db.backup.fs.file cascades to ir.attachment.unlink(), + which marks the file in fs.file.gc for deferred deletion by the + autovacuum job. + """ for db_backup_conf in self.filtered( lambda record: record.method == "fs_file" and record.days_to_keep ): with db_backup_conf.cleanup_log(): to_delete = db_backup_conf.fs_file_backup_ids.filtered("is_expired") - for backup in to_delete: - self._get_fs_storage().fs.rm_file(backup.get_fs_storage_filename()) to_delete.unlink() res = super().cleanup() return res From 633dc52e4605c55c1108f6d68c6afcdd6daaa4fe Mon Sep 17 00:00:00 2001 From: "r.perez" Date: Tue, 21 Jul 2026 19:57:38 -0400 Subject: [PATCH 4/5] [IMP] auto_backup_fs_file: add regression test for action_backup cleanup trigger --- .../tests/test_auto_backup_fs_file.py | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/auto_backup_fs_file/tests/test_auto_backup_fs_file.py b/auto_backup_fs_file/tests/test_auto_backup_fs_file.py index d169e8e6132..29d7b82e43d 100644 --- a/auto_backup_fs_file/tests/test_auto_backup_fs_file.py +++ b/auto_backup_fs_file/tests/test_auto_backup_fs_file.py @@ -70,6 +70,7 @@ def test_ordinary_flow(self): backup_config.name, f"Fs File Backup - {backup_config._get_fs_storage().name}", ) + self.assertFalse(backup_config.folder) # Test computation of fs_file_backup_count self.assertEqual(backup_config.fs_file_backup_count, 0) @@ -121,3 +122,51 @@ def fake_now(): backup_config.cleanup() # Will use the computed is_expired self.assertEqual(backup_config.fs_file_backup_count, 0) + + # Verify the backing ir.attachment is also removed (GC chain fires via unlink) + attachment = self.env["ir.attachment"].search( + [ + ("res_model", "=", "db.backup.fs.file"), + ("res_field", "=", "backup_file"), + ] + ) + self.assertFalse(attachment) + + def test_action_backup_triggers_cleanup(self): + """cleanup() must fire for fs_file records via action_backup(), not just + when called directly. Regression test for the bug where action_backup() + only passed local/sftp records to successful.cleanup(), making fs_file + cleanup dead code in production.""" + self.test_storage.field_xmlids = ( + "auto_backup_fs_file.field_db_backup_fs_file__backup_file" + ) + backup_config = self._create_backup_config() + + # Run first backup — creates record at create_date = now + self._action_backup(backup_config) + self.assertEqual(backup_config.fs_file_backup_count, 1) + first_backup = backup_config.fs_file_backup_ids + + # Make the first backup expired by setting an old create_date directly + # (avoids patching Datetime.now which doesn't control ORM create_date) + old_date = fields.Datetime.add( + fields.Datetime.now(), days=-backup_config.days_to_keep - 1 + ) + self.env.cr.execute( + "UPDATE db_backup_fs_file SET create_date = %s WHERE id = %s", + (old_date, first_backup.id), + ) + first_backup.invalidate_recordset(["is_expired", "create_date"]) + self.assertTrue(first_backup.is_expired) + + # Run second backup via action_backup() — this is the PRODUCTION call path. + # cleanup() must be triggered automatically for the expired first backup. + self._action_backup(backup_config) + + # First backup must be gone (cleanup deleted it) + self.assertFalse( + first_backup.exists(), + "Expired backup was not deleted by action_backup()", + ) + # A new backup should have been created + self.assertTrue(backup_config.fs_file_backup_ids) From 25c86a4f53b08e30164caeb3b4c09cb85aeafb62 Mon Sep 17 00:00:00 2001 From: "r.perez" Date: Tue, 21 Jul 2026 19:59:23 -0400 Subject: [PATCH 5/5] [IMP] auto_backup_fs_file: update docs for GC-based cleanup and folder visibility --- auto_backup_fs_file/README.rst | 139 +++++++++++------- auto_backup_fs_file/readme/CONTEXT.md | 2 + auto_backup_fs_file/readme/INSTALL.md | 2 +- auto_backup_fs_file/readme/ROADMAP.md | 2 +- auto_backup_fs_file/readme/USAGE.md | 12 ++ .../static/description/index.html | 117 +++++++++------ 6 files changed, 171 insertions(+), 103 deletions(-) diff --git a/auto_backup_fs_file/README.rst b/auto_backup_fs_file/README.rst index 0b52bbbd1af..2573c602e66 100644 --- a/auto_backup_fs_file/README.rst +++ b/auto_backup_fs_file/README.rst @@ -1,7 +1,3 @@ -.. image:: https://odoo-community.org/readme-banner-image - :target: https://odoo-community.org/get-involved?utm_source=readme - :alt: Odoo Community Association - =================== Auto Backup Fs File =================== @@ -17,7 +13,7 @@ Auto Backup Fs File .. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png :target: https://odoo-community.org/page/development-status :alt: Alpha -.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github @@ -69,12 +65,12 @@ network drives, or other custom filesystems supported by ``fsspec``. Practical examples include: -- Backing up Odoo data to cloud storage providers like AWS S3, Google - Cloud Storage, or Azure Blob Storage. -- Storing backups on a secure local or remote filesystem for disaster - recovery purposes. -- Automating backup processes in multi-environment setups, such as - multi-company or multi-website configurations. +- Backing up Odoo data to cloud storage providers like AWS S3, Google + Cloud Storage, or Azure Blob Storage. +- Storing backups on a secure local or remote filesystem for disaster + recovery purposes. +- Automating backup processes in multi-environment setups, such as + multi-company or multi-website configurations. APPROACH: The module extends the backup functionality from the ``auto_backup`` module by introducing a method that allows storing the @@ -87,18 +83,27 @@ exporting Odoo instance data and storing it in the specified filesystem. Additionally, it allows users to download the backups for local storage or further processing. +Backup file cleanup is handled automatically based on the **Days to +Keep** configuration. When expired backup records are removed, the +physical backup files are not deleted synchronously. Instead, the module +delegates file deletion to the ``fs_attachment`` garbage collector (GC), +which marks files for deferred removal and physically deletes them +during Odoo's autovacuum cron cycle. This two-phase approach ensures +transactional safety: files are only removed once the GC confirms no +database record still references them. + USEFUL INFORMATION: -- **Dependencies**: This module depends on the ``fsspec`` library, its - relevant filesystem implementations, and the ``fs_file`` addon from - OCA/storage. Ensure the required ``fsspec`` plugins are installed for - your target filesystem. +- **Dependencies**: This module depends on the ``fsspec`` library, its + relevant filesystem implementations, and the ``fs_file`` addon from + OCA/storage. Ensure the required ``fsspec`` plugins are installed for + your target filesystem. Installation ============ This addon itself does not introduce any dependencies, but its -dependencies may require additional packages.:wa +dependencies may require additional packages. Configuration ============= @@ -107,37 +112,36 @@ Configuration module, ensure you have reviewed the documentation for the following modules: -- ``fs_attachment`` -- ``fs_storage`` These modules provide the necessary setup for file - storage and attachment handling. +- ``fs_attachment`` +- ``fs_storage`` These modules provide the necessary setup for file + storage and attachment handling. 2. **Configure File Storage** -- Navigate to **Settings** > **Technical** > **FS Storage**. -- Create or select an existing storage configuration. -- Ensure the storage is properly set up and tested for accessibility. +- Navigate to **Settings** > **Technical** > **FS Storage**. +- Create or select an existing storage configuration. +- Ensure the storage is properly set up and tested for accessibility. 3. **Link Backup File field to Storage** -- While configuring the file storage in **Settings** > **Technical** > - **FS Storage**, ensure that the ``backup_file`` from the - ``db.backup.fs.file`` model is listed under the ``Field`` field. -- This step is part of the storage configuration process. -- Save the changes after verifying the setup. +- While configuring the file storage in **Settings** > **Technical** > + **FS Storage**, ensure that the ``backup_file`` from the + ``db.backup.fs.file`` model is listed under the ``Field`` field. +- This step is part of the storage configuration process. +- Save the changes after verifying the setup. -|Example of File Storage Configuration| +.. image:: https://raw.githubusercontent.com/OCA/server-tools/17.0/auto_backup_fs_file/images/file_storage_configuration.png + :alt: Example of File Storage Configuration 4. **Verify Configuration** -- Perform a test backup to ensure the files are being stored in the - correct location. -- Check the logs for any errors or warnings. +- Perform a test backup to ensure the files are being stored in the + correct location. +- Check the logs for any errors or warnings. By following these steps, you will ensure that the module is properly configured for storing backups in the desired file storage system. -.. |Example of File Storage Configuration| image:: https://raw.githubusercontent.com/OCA/server-tools/17.0/auto_backup_fs_file/images/file_storage_configuration.png - Usage ===== @@ -179,24 +183,49 @@ How to Use the Module 4. Manage Fs File Backups ~~~~~~~~~~~~~~~~~~~~~~~~~ -- In the Fs File backups list view, you can see details such as the - backup filename and associated database backup configuration. -- Use this view to manage or download backups as needed. +- In the Fs File backups list view, you can see details such as the + backup filename and associated database backup configuration. +- Use this view to manage or download backups as needed. + +5. Cleanup and File Deletion +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Backup retention is controlled by the **Days to Keep** field on the +backup configuration. When this value is greater than 0, the automatic +cleanup process removes expired backup records during each backup run. + +When a backup record is deleted (either by automatic cleanup or manually +from the list view), the physical backup file in the filesystem storage +is **not removed immediately**. Instead, the file is marked for deferred +deletion by the ``fs_attachment`` garbage collector (GC), which runs +periodically via Odoo's autovacuum cron. Physical files are only removed +from the storage backend once the GC confirms no database record +references them. + +This means: + +- **Immediately after deletion**: the database record is gone, but the + file may still exist in the storage backend for a short period. +- **After the next autovacuum cycle**: the file is permanently deleted + from the storage backend. + +This behavior requires the storage's ``autovacuum_gc`` flag to be +enabled (the default). If disabled, files must be managed manually. Screenshots ~~~~~~~~~~~ -- **Backup Configuration Form View** |Backup Configuration Form| +- **Backup Configuration Form View** |Backup Configuration Form| -- **Fs File Backups List View** |Fs File Backups List| +- **Fs File Backups List View** |Fs File Backups List| Notes ~~~~~ -- Ensure that the FSSPEC storage is properly configured before using the - **Fs File** method. -- This module adds a new stat button in the backup configuration form - view to quickly access Fs File backups. +- Ensure that the FSSPEC storage is properly configured before using + the **Fs File** method. +- This module adds a new stat button in the backup configuration form + view to quickly access Fs File backups. .. |Backup Configuration Form| image:: https://raw.githubusercontent.com/OCA/server-tools/17.0/auto_backup_fs_file/static/description/db_backup_form_view.png .. |Fs File Backups List| image:: https://raw.githubusercontent.com/OCA/server-tools/17.0/auto_backup_fs_file/static/description/db_backup_fs_file_tree_view.png @@ -204,18 +233,18 @@ Notes Known issues / Roadmap ====================== -- **Folder field behavior**: The ``folder`` field on the ``db.backup`` - model specifies the backup storage directory. For records using the - ``fs_file`` method, storage is actually controlled by the ``fs_file`` - field's settings. However, since ``folder`` is currently a required - non-computed field in the ``auto_backup`` addon, modifications to sync - these two fields are not performed. Future versions may add this - synchronization support. +- **Folder field behavior**: The ``folder`` field on the ``db.backup`` + model specifies the backup storage directory. For records using the + ``fs_file`` method, storage is controlled by the ``fs_file`` field's + settings. The ``folder`` field is hidden (``invisible``) and no + longer required when ``method='fs_file'``, so it no longer interferes + with ``fs_file`` configurations. No auto-sync between both fields is + performed since the methods are mutually exclusive. -- **Design limitation**: The current implementation has a design - constraint due to ``fs_storage`` addon limitations. Since storage - setting targets the ``db.backup.fs.file`` model, only one storage - backend can effectively be used. +- **Design limitation**: The current implementation has a design + constraint due to ``fs_storage`` addon limitations. Since storage + setting targets the ``db.backup.fs.file`` model, only one storage + backend can effectively be used. Bug Tracker =========== @@ -238,14 +267,14 @@ Authors Contributors ------------ -- Rolando Pérez Rebollo r.perez@binhex.cloud +- Rolando Pérez Rebollo r.perez@binhex.cloud Other credits ------------- The development of this module has been financially supported by: -- Binhex +- Binhex Maintainers ----------- diff --git a/auto_backup_fs_file/readme/CONTEXT.md b/auto_backup_fs_file/readme/CONTEXT.md index fe771bb0775..476024d83ee 100644 --- a/auto_backup_fs_file/readme/CONTEXT.md +++ b/auto_backup_fs_file/readme/CONTEXT.md @@ -9,5 +9,7 @@ Practical examples include: APPROACH: The module extends the backup functionality from the `auto_backup` module by introducing a method that allows storing the resulting backup using an `fsspec` implementation. This is achieved through the integration of the `fs_file` from [storage repository](https://github.com/OCA/storage). The module leverages the `fsspec` library to provide a flexible and extensible interface for interacting with various filesystems. It automates the backup process by exporting Odoo instance data and storing it in the specified filesystem. Additionally, it allows users to download the backups for local storage or further processing. + Backup file cleanup is handled automatically based on the **Days to Keep** configuration. When expired backup records are removed, the physical backup files are not deleted synchronously. Instead, the module delegates file deletion to the `fs_attachment` garbage collector (GC), which marks files for deferred removal and physically deletes them during Odoo's autovacuum cron cycle. This two-phase approach ensures transactional safety: files are only removed once the GC confirms no database record still references them. + USEFUL INFORMATION: - **Dependencies**: This module depends on the `fsspec` library, its relevant filesystem implementations, and the `fs_file` addon from OCA/storage. Ensure the required `fsspec` plugins are installed for your target filesystem. diff --git a/auto_backup_fs_file/readme/INSTALL.md b/auto_backup_fs_file/readme/INSTALL.md index f60d5acfaa5..bf5358ca486 100644 --- a/auto_backup_fs_file/readme/INSTALL.md +++ b/auto_backup_fs_file/readme/INSTALL.md @@ -1 +1 @@ -This addon itself does not introduce any dependencies, but its dependencies may require additional packages.:wa +This addon itself does not introduce any dependencies, but its dependencies may require additional packages. diff --git a/auto_backup_fs_file/readme/ROADMAP.md b/auto_backup_fs_file/readme/ROADMAP.md index a3a695bc2b8..26e6ecbd01a 100644 --- a/auto_backup_fs_file/readme/ROADMAP.md +++ b/auto_backup_fs_file/readme/ROADMAP.md @@ -1,3 +1,3 @@ -- **Folder field behavior**: The `folder` field on the `db.backup` model specifies the backup storage directory. For records using the `fs_file` method, storage is actually controlled by the `fs_file` field's settings. However, since `folder` is currently a required non-computed field in the `auto_backup` addon, modifications to sync these two fields are not performed. Future versions may add this synchronization support. +- **Folder field behavior**: The `folder` field on the `db.backup` model specifies the backup storage directory. For records using the `fs_file` method, storage is controlled by the `fs_file` field's settings. The `folder` field is hidden (`invisible`) and no longer required when `method='fs_file'`, so it no longer interferes with `fs_file` configurations. No auto-sync between both fields is performed since the methods are mutually exclusive. - **Design limitation**: The current implementation has a design constraint due to `fs_storage` addon limitations. Since storage setting targets the `db.backup.fs.file` model, only one storage backend can effectively be used. diff --git a/auto_backup_fs_file/readme/USAGE.md b/auto_backup_fs_file/readme/USAGE.md index b1b2cc0a190..0f2a7459c5e 100644 --- a/auto_backup_fs_file/readme/USAGE.md +++ b/auto_backup_fs_file/readme/USAGE.md @@ -23,6 +23,18 @@ This module extends the functionality of the database backup system in Odoo by i - In the Fs File backups list view, you can see details such as the backup filename and associated database backup configuration. - Use this view to manage or download backups as needed. +### 5. Cleanup and File Deletion + +Backup retention is controlled by the **Days to Keep** field on the backup configuration. When this value is greater than 0, the automatic cleanup process removes expired backup records during each backup run. + +When a backup record is deleted (either by automatic cleanup or manually from the list view), the physical backup file in the filesystem storage is **not removed immediately**. Instead, the file is marked for deferred deletion by the `fs_attachment` garbage collector (GC), which runs periodically via Odoo's autovacuum cron. Physical files are only removed from the storage backend once the GC confirms no database record references them. + +This means: +- **Immediately after deletion**: the database record is gone, but the file may still exist in the storage backend for a short period. +- **After the next autovacuum cycle**: the file is permanently deleted from the storage backend. + +This behavior requires the storage's `autovacuum_gc` flag to be enabled (the default). If disabled, files must be managed manually. + ### Screenshots - **Backup Configuration Form View** ![Backup Configuration Form](../static/description/db_backup_form_view.png) diff --git a/auto_backup_fs_file/static/description/index.html b/auto_backup_fs_file/static/description/index.html index 967556011f1..092ade5a4f2 100644 --- a/auto_backup_fs_file/static/description/index.html +++ b/auto_backup_fs_file/static/description/index.html @@ -3,7 +3,7 @@ -README.rst +Auto Backup Fs File -
+
+

Auto Backup Fs File

- - -Odoo Community Association - -
-

Auto Backup Fs File

-

Alpha License: AGPL-3 OCA/server-tools Translate me on Weblate Try me on Runboat

+

Alpha License: AGPL-3 OCA/server-tools Translate me on Weblate Try me on Runboat

This module enhances the database backup functionality in Odoo by introducing support for storing backups as files using the fsspec library. It is designed to address the need for reliable and flexible @@ -405,25 +400,26 @@

Auto Backup Fs File

  • 2. Perform a Backup
  • 3. View Fs File Backups
  • 4. Manage Fs File Backups
  • -
  • Screenshots
  • -
  • Notes
  • +
  • 5. Cleanup and File Deletion
  • +
  • Screenshots
  • +
  • Notes
  • -
  • Known issues / Roadmap
  • -
  • Bug Tracker
  • -
  • Credits
  • -

    Use Cases / Context

    +

    Use Cases / Context

    BUSINESS NEED: This module addresses the critical need for safeguarding Odoo instance data by enabling automated backups to a filesystem supported by the fsspec library. Businesses often require reliable @@ -450,6 +446,14 @@

    Use Cases / Context

    exporting Odoo instance data and storing it in the specified filesystem. Additionally, it allows users to download the backups for local storage or further processing.

    +

    Backup file cleanup is handled automatically based on the Days to +Keep configuration. When expired backup records are removed, the +physical backup files are not deleted synchronously. Instead, the module +delegates file deletion to the fs_attachment garbage collector (GC), +which marks files for deferred removal and physically deletes them +during Odoo’s autovacuum cron cycle. This two-phase approach ensures +transactional safety: files are only removed once the GC confirms no +database record still references them.

    USEFUL INFORMATION:

    • Dependencies: This module depends on the fsspec library, its @@ -459,12 +463,12 @@

      Use Cases / Context

    -

    Installation

    +

    Installation

    This addon itself does not introduce any dependencies, but its -dependencies may require additional packages.:wa

    +dependencies may require additional packages.

    -

    Configuration

    +

    Configuration

    1. Review Documentation for Dependencies Before configuring the module, ensure you have reviewed the documentation for the following @@ -493,7 +497,7 @@

      Configuration

    2. This step is part of the storage configuration process.
    3. Save the changes after verifying the setup.
    4. -

      Example of File Storage Configuration

      +Example of File Storage Configuration
      1. Verify Configuration
      @@ -506,14 +510,14 @@

      Configuration

      configured for storing backups in the desired file storage system.

    -

    Usage

    +

    Usage

    This module extends the functionality of the database backup system in Odoo by introducing a new backup method: Fs File. This method allows storing database backups as files using an FSSPEC implementation.

    -

    How to Use the Module

    +

    How to Use the Module

    -

    1. Configure the Backup Method

    +

    1. Configure the Backup Method

    1. Navigate to Settings > Technical > Database Structure > Automated Backups.
    2. @@ -525,7 +529,7 @@

      1. Configure the Backup Method

    -

    2. Perform a Backup

    +

    2. Perform a Backup

    1. From the list of backup configurations, select the one configured with the Fs File method.
    2. @@ -534,7 +538,7 @@

      2. Perform a Backup

    -

    3. View Fs File Backups

    +

    3. View Fs File Backups

    1. Open the backup configuration form view.
    2. In the top-right corner, you will see a Backups stat button (if @@ -544,25 +548,47 @@

      3. View Fs File Backups

    -

    4. Manage Fs File Backups

    +

    4. Manage Fs File Backups

    • In the Fs File backups list view, you can see details such as the backup filename and associated database backup configuration.
    • Use this view to manage or download backups as needed.
    +
    +

    5. Cleanup and File Deletion

    +

    Backup retention is controlled by the Days to Keep field on the +backup configuration. When this value is greater than 0, the automatic +cleanup process removes expired backup records during each backup run.

    +

    When a backup record is deleted (either by automatic cleanup or manually +from the list view), the physical backup file in the filesystem storage +is not removed immediately. Instead, the file is marked for deferred +deletion by the fs_attachment garbage collector (GC), which runs +periodically via Odoo’s autovacuum cron. Physical files are only removed +from the storage backend once the GC confirms no database record +references them.

    +

    This means:

    +
      +
    • Immediately after deletion: the database record is gone, but the +file may still exist in the storage backend for a short period.
    • +
    • After the next autovacuum cycle: the file is permanently deleted +from the storage backend.
    • +
    +

    This behavior requires the storage’s autovacuum_gc flag to be +enabled (the default). If disabled, files must be managed manually.

    +
    -

    Screenshots

    +

    Screenshots

    • Backup Configuration Form View Backup Configuration Form
    • Fs File Backups List View Fs File Backups List
    -

    Notes

    +

    Notes

      -
    • Ensure that the FSSPEC storage is properly configured before using the -Fs File method.
    • +
    • Ensure that the FSSPEC storage is properly configured before using +the Fs File method.
    • This module adds a new stat button in the backup configuration form view to quickly access Fs File backups.
    @@ -570,15 +596,15 @@

    Notes

    -

    Known issues / Roadmap

    +

    Known issues / Roadmap

    • Folder field behavior: The folder field on the db.backup model specifies the backup storage directory. For records using the -fs_file method, storage is actually controlled by the fs_file -field’s settings. However, since folder is currently a required -non-computed field in the auto_backup addon, modifications to sync -these two fields are not performed. Future versions may add this -synchronization support.
    • +fs_file method, storage is controlled by the fs_file field’s +settings. The folder field is hidden (invisible) and no +longer required when method='fs_file', so it no longer interferes +with fs_file configurations. No auto-sync between both fields is +performed since the methods are mutually exclusive.
    • Design limitation: The current implementation has a design constraint due to fs_storage addon limitations. Since storage setting targets the db.backup.fs.file model, only one storage @@ -586,7 +612,7 @@

      Known issues / Roadmap

    -

    Bug Tracker

    +

    Bug Tracker

    Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -594,28 +620,28 @@

    Bug Tracker

    Do not contact contributors directly about support or help with technical issues.

    -

    Credits

    +

    Credits

    -

    Authors

    +

    Authors

    • Binhex
    -

    Other credits

    +

    Other credits

    The development of this module has been financially supported by:

    • Binhex
    -

    Maintainers

    +

    Maintainers

    This module is maintained by the OCA.

    Odoo Community Association @@ -628,6 +654,5 @@

    Maintainers

    -