Skip to content

feat: clean up old revisions according to a cleanup strategy - #3778

Draft
pbleser-oc wants to merge 4 commits into
opencloud-eu:mainfrom
pbleser-oc:feat/1419-clean-up-file-versions
Draft

pbleser-oc wants to merge 4 commits into
opencloud-eu:mainfrom
pbleser-oc:feat/1419-clean-up-file-versions

Conversation

@pbleser-oc

@pbleser-oc pbleser-oc commented Oct 21, 2026 •

Copy link
Copy Markdown
Member

Description

The OpenCloud side of the revision cleanup: old revisions (versions) of files are deleted according to a configurable cleanup strategy, for the decomposed, decomposeds3 and posix storage drivers. The cleanup itself is in reva, opencloud-eu/reva#895; this PR configures it and adds a command to run it on demand.

Caution

Draft until opencloud-eu/reva#895 is merged. The first commit temporarily points github.com/opencloud-eu/reva/v2 at the head of #895 in its fork, with a replace in go.mod, and re-vendors, so that this PR builds and CI runs. Once #895 is merged, that commit is replaced by a regular reva bump.

DO NOT MERGE BEFORE opencloud-eu/reva#895

Configuration

A revisions_cleanup section of the storage-users configuration, passed to all three drivers, in the storage provider and the data provider:

environment variable default meaning
OC_REVISIONS_CLEANUP_STRATEGY disabled which old revisions to delete whenever a file gets a new revision, e.g. auto, 30d, 10, 5, 30d or 7d, auto, 90d
OC_REVISIONS_CLEANUP_ASYNC true run the cleanup in background workers, so it doesn't slow down the upload, restore or change on disk that created the revision
OC_REVISIONS_CLEANUP_ASYNC_WORKERS 0 (half the CPUs, at least 2) number of background workers
OC_REVISIONS_CLEANUP_ASYNC_QUEUE_SIZE 0 (64 per worker) number of files that can wait for a worker
OC_REVISIONS_CLEANUP_ASYNC_QUEUE_FULL block block waits for room, drop skips the cleanup of that file until its next revision

The default keeps all revisions, as before. An invalid strategy makes the storage-users service fail at startup.

opencloud storage-users revisions cleanup

The service only cleans up a file when it gets a new revision. The command covers the files that aren't changed anymore, and applies a different strategy once, e.g. after the strategy was changed or to free storage:

  • which files: --space (repeatable, with --path for a file or folder within the space), --all, or --fs-path (a file or folder by its path on disk, posix only);
  • how: --strategy and the settings of the background workers (--async, --workers, --queue-size, --queue-full) default to the configured ones;
  • output: a line for every file whose revisions were deleted, that failed or that was skipped, with its path within its space, and a summary; --verbose adds every revision with the decision and its reason; --json prints JSON objects, one per line;
  • --dry-run deletes nothing;
  • --timeout stops gracefully, as does ctrl-c; --shuffle walks the spaces and folders in a random order, so that repeated runs, e.g. a nightly cron job, eventually reach all files;
  • exit codes: 0 when done, 1 if the cleanup or any file failed, 2 if the timeout stopped it before all files were cleaned up.

Short flags: -a, -p, -s, -n, -v, -j, -t. The command uses the storage driver directly, in its own process, like uploads sessions: posix neither scans nor watches the file system, and no driver joins the postprocessing consumer group.

opencloud storage-users revisions cleanup --all --strategy "auto, 90d" --dry-run --verbose
opencloud storage-users revisions cleanup --space <space id> --path /Documents --strategy 10
opencloud storage-users revisions cleanup --all --timeout 1h --shuffle

The storage-users README documents the configuration, the strategies, the command and its output, with examples. The admin documentation in opencloud-eu/docs follows separately.

Commits

  1. chore: temporarily use reva from opencloud-eu/reva#895 (to be replaced by a reva bump)
  2. feat: 1419: configure the revision cleanup of the storage-users drivers
  3. feat: 1419: add a command to clean up old revisions on demand
  4. test: 1419: acceptance tests for the revision cleanup

Every commit builds from vendor/ and passes the storage-users tests.

Related Issue

Motivation and Context

Every change to a file keeps the previous content as a revision, forever. Without a cleanup, revisions accumulate and use up storage, and the only way to get rid of them was to delete the files or to disable versioning, which keeps the revisions that exist. #1419 asks for a configurable cleanup that runs automatically, without slowing down writes, and that can also be run on demand for spaces, folders or files.

How Has This Been Tested?

  • unit tests: the configuration reaching all three drivers (revaconfig), and the command: flag validation, the strategy and worker defaults, text and JSON output, the exit codes (command)
  • acceptance tests: a new feature, tests/acceptance/features/cliCommands/cleanupFileVersions.feature, with 10 scenarios against a running server, checking the remaining versions through the WebDAV versions API: all spaces, a dry run, a folder within the personal space, a project space, the JSON output, no strategy while the configured one is disabled (exit code 1), a timeout (exit code 2), a strategy without spaces after its commas, a folder by its path on disk (posix only), and the configured strategy cleaning up on every new version. Run locally on posix (10/10) and decomposed (9/9, the posix-only scenario is skipped).
  • end to end: a scripted run against a single-binary server with posix: files with revisions created over WebDAV, then the command (dry run, a folder, JSON output, an invalid scope, a timeout, all spaces) next to the running server, checking the revisions on disk, the versions API and the file contents.
  • the reva side is tested in feat: clean up old revisions according to a cleanup strategy reva#895.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Technical debt
  • Tests only (no source changes)

Checklist:

  • Code changes
  • Unit tests added
  • Acceptance tests added
  • Documentation added

@codacy-production

codacy-production Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 130 complexity

Metric Results
Complexity 130

View in Codacy

🟢 Coverage 78.87% diff coverage

Metric Results
Coverage variation Report missing for 5d745311
Diff coverage ✅ 78.87% diff coverage

View coverage diff in Codacy

Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (5d74531) Report Missing Report Missing Report Missing
Head commit (0f568a5) 93066 25768 27.69%

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#3778) 426 336 78.87%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

1 Codacy didn't receive coverage data for the commit, or there was an error processing the received data. Check your integration for errors and validate that your coverage setup is correct.

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@pbleser-oc
pbleser-oc force-pushed the feat/1419-clean-up-file-versions branch 2 times, most recently from 5026cda to 1103975 Compare October 21, 2026 16:51
pbleser-oc added a commit to pbleser-oc/docs that referenced this pull request Oct 22, 2026
OpenCloud can now delete old file versions according to a cleanup
strategy (opencloud-eu/opencloud#1419, opencloud-eu/opencloud#3778).

- a new page, Cleaning Up Old Versions, in the storage configuration:
  what the cleanup does and when it runs, how to turn it on with
  OpenCloud Compose and other installations, the strategies explained
  with one example file throughout, how the age of a version is
  measured, how to try a strategy out, the background workers and the
  logs
- the command to clean up versions on demand, in the maintenance
  commands: a dry run first, selecting the files, choosing the
  strategy, the output, a nightly cron job with a timeout, the exit
  codes
- features and FAQ: versions are kept by default, administrators can
  have old ones deleted
@pbleser-oc
pbleser-oc force-pushed the feat/1419-clean-up-file-versions branch from 1103975 to 463d83b Compare October 23, 2026 06:22
@pbleser-oc
pbleser-oc force-pushed the feat/1419-clean-up-file-versions branch from 463d83b to 13b56eb Compare October 23, 2026 06:54
@pbleser-oc
pbleser-oc force-pushed the feat/1419-clean-up-file-versions branch 2 times, most recently from 5ba90c2 to 411b6b4 Compare October 25, 2026 01:13
pbleser-oc added a commit to pbleser-oc/docs that referenced this pull request Oct 25, 2026
OpenCloud can now delete old file versions according to a cleanup
strategy (opencloud-eu/opencloud#1419, opencloud-eu/opencloud#3778).

- a new page, Cleaning Up Old Versions, in the storage configuration:
  what the cleanup does and when it runs, how to turn it on with
  OpenCloud Compose and other installations, the strategies explained
  with one example file throughout, how the age of a version is
  measured, how to try a strategy out, the background workers and the
  logs
- the command to clean up versions on demand, in the maintenance
  commands: a dry run first, selecting the files, choosing the
  strategy, the output, a nightly cron job with a timeout, the exit
  codes, and what to know when it runs while OpenCloud is running
  (versions in an open Versions panel, NATS for PosixFS)
- features and FAQ: versions are kept by default, administrators can
  have old ones deleted
@maki5 maki5 removed the status in OpenCloud Team Board Oct 28, 2026
Points github.com/opencloud-eu/reva/v2 at the head of
opencloud-eu/reva#895 in its fork (pbleser-oc/reva 414fb6332), which
adds the revision cleanup this branch configures and calls, and
re-vendors.

Temporary: to be replaced by a regular reva bump once
opencloud-eu/reva#895 is merged.
Wire reva's revision cleanup options into the 'decomposed', 'decomposeds3'
and 'posix' drivers, in the storage provider and in the data provider.

The options are a single 'revisions_cleanup' section of the storage-users
configuration, next to 'filemetadata_cache' and 'id_cache', as only one
driver is used at a time. Its environment variables:

- OC_REVISIONS_CLEANUP_STRATEGY: which old revisions to delete whenever a
  file gets a new revision, e.g. 'auto', '30d' or '7d, auto, 90d'
- OC_REVISIONS_CLEANUP_ASYNC: run the cleanup in background workers
- OC_REVISIONS_CLEANUP_ASYNC_WORKERS: number of background workers
- OC_REVISIONS_CLEANUP_ASYNC_QUEUE_SIZE: number of files that can wait
- OC_REVISIONS_CLEANUP_ASYNC_QUEUE_FULL: 'drop' or 'block'
- OC_REVISIONS_CLEANUP_ASYNC_QUEUE_FULL_TIMEOUT: how long 'block' waits
  for room at most, 0 for as long as it takes

The strategy defaults to 'disabled', which keeps all revisions as before.
The other defaults are reva's: background workers, with the number of
workers and the queue size determined automatically, dropping the
cleanup of a file when the queue is full (it is cleaned up with its
next revision), and a timeout of 5s for 'block'.
opencloud storage-users revisions cleanup deletes old revisions of the
files of spaces (--space, repeatable), of a file or folder within a
space (--space with --path), of all spaces (--all), or of a file or
folder given by its path on disk (--fs-path, posix only), according to
a cleanup strategy. The storage-users service only cleans up the
revisions of a file when it gets a new one; this also covers the files
that are not changed anymore, and applies a different strategy once.

The strategy and the settings of the background workers default to the
configured ones (OC_REVISIONS_CLEANUP_*), and can be overridden with
--strategy, --async, --workers and --queue-size. Only --queue-full
defaults to 'block' without a timeout, whatever is configured: the
command finds files faster than the workers clean them up, so dropping
the files that find the queue full, or giving up after the timeout
meant for uploads, would skip most of them. --queue-full-timeout sets
one for the run.

The command uses the storage driver directly, in its own process, like
'uploads sessions': posix neither scans nor watches the file system, and
no driver joins the postprocessing consumer group of the service.

For posix, the driver needs NATS for its event stream. The command waits
for it 10 seconds at most, instead of the 15 minutes the stream retries
for, and ctrl-c also stops that wait: with the single binary, NATS only
runs within the server (opencloud-eu#3805).

Output: a line for every file whose revisions were deleted, that failed
or that was skipped, with its path within its space, and a summary;
--verbose adds every file and every revision with the decision and its
reason; --json prints the same as JSON objects, one per line, with a
final summary object. --dry-run deletes nothing.

--timeout stops the cleanup gracefully, as does ctrl-c; --shuffle walks
the spaces and folders in a random order, so that repeated runs that
are stopped by the timeout, e.g. from a cron job, eventually reach all
files. The help explains that a file waiting for a lock can't be
interrupted, and that a dry run can still create lock files.

The common flags have short forms: -a (--all), -p (--fs-path),
-s (--strategy), -n (--dry-run), -v (--verbose), -j (--json) and
-t (--timeout).

Exit codes: 0 when done, 1 if the cleanup or any file failed, 2 if the
timeout stopped the cleanup before all files were cleaned up.

The storage-users README documents the command, along with the cleanup
strategies and how they relate to the configured cleanup.
A new cliCommands feature, cleanupFileVersions.feature, tests the
"storage-users revisions cleanup" command against a running server,
checking the remaining versions through the WebDAV versions API:

- keeping the newest version of every file in all spaces
- a dry run, which deletes nothing
- only a folder within the personal space (--space with --path)
- only a project space (--space)
- the JSON output (--json)
- no strategy while the configured one is disabled: exit code 1
- a timeout: exit code 2, nothing deleted
- a strategy without spaces after its commas ("auto,1"), as the CLI
  wrapper splits commands on spaces
- a folder by its path on disk (--fs-path), posix only
- the configured strategy (OC_REVISIONS_CLEANUP_STRATEGY), which cleans
  up a file whenever it gets a new version

New steps: in CliContext, running the command for all spaces, a space,
a path within a space, a path on the POSIX filesystem, or with flags
only; checking the exact exit code; and checking the objects of a JSON
output, which "the command output should contain" can't match as it
contains quotes. In FilesVersionsContext, a number of versions that is
checked until it matches, for the cleanup that runs in the background
after postprocessing.
@pbleser-oc
pbleser-oc force-pushed the feat/1419-clean-up-file-versions branch from 411b6b4 to 0f568a5 Compare October 28, 2026 17:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🧹 Clean-Up File Versions

1 participant