Commit Graph

41 Commits

Author SHA1 Message Date
dillard 942e8ec003 Web interface: dates and times in the user's Nextcloud locale 2026-10-15 21:43:09 +02:00
dillard 144097d159 Run the backup job at every cron run; skip deflate on compressed data 2026-10-15 20:59:04 +02:00
dillard 5b7dd08e71 Ask for feedback on the admin page, with an experience report form 2026-10-15 10:32:21 +02:00
dillard ca003c88ba Fast S3 verify and snapshot commit; shorter runs list; durations with days
On S3, index files and the tree segments read back when a snapshot is
written are fetched 16 at a time through the storage's S3 client
(IBackend::getRanges(), getMany()). Blobs that follow each other in a pack
are read as one range on every location. The snapshot is written in a step
of its own and the run shows "commit" meanwhile. On a 1 TB production
repository the check went from about 4 hours to 3.5 minutes.

backup:status and the web interface list the runs of the last 7 days,
running ones and at least the newest 5; --all / "Show older runs" list
all. Durations of a day or more show the days.
2026-10-14 17:12:41 +02:00
dillard c38cc47534 Release 0.9.6-beta.7 2026-10-14 13:14:46 +02:00
dillard dfd3f38d8c Backups to SMB no longer crawl; add occ backup:cancel
Each 30-second step opened the location again and read its list of
index files. Over SMB that cost a request per file, so on a large
repository opening took longer than the step: each step stored one
4 MiB pack and the list grew further. A first backup of nc01 to a
Storage Box over SMB managed 12 GiB in 35 hours.

occ backup:run and system cron now keep the repository open for the
whole run (reopened when another process took a step or the location
was edited), opening no longer counts towards the step's time, and
SMB folders are listed in one request.

occ backup:cancel stops a running backup: no new step starts and the
step in progress finishes first. A run of an earlier version, which
does not hold back its next step, is marked cancelled after two
minutes unless it is recording its snapshot.
2026-10-14 12:15:27 +02:00
dillard 92e693cfe6 Runs list: show the total size of each backup next to what it uploaded 2026-10-13 11:02:18 +02:00
dillard 025bbfbb62 Verify: list the pack folders only with more packs than folders
With few packs a request per pack is fewer requests than 256 listings. On
FTP every listing takes a data connection; the FTP server of the integration
tests has ten passive ports, and 256 listings in a row slowed it down until a
read failed ("Not found: snapshots/...").
2026-10-12 14:50:56 +02:00
dillard 8ed7455619 Release 0.9.5-beta.6 2026-10-12 14:27:39 +02:00
dillard 30a250bc11 Stale-backup notification: "No successful backup to … yet" instead of "since never" 2026-10-12 11:32:42 +02:00
dillard 9c06ab2841 SFTP: replace a dropped connection; write the index cache in one transaction
A Hetzner Storage Box drops an SFTP connection that carried a lot of data
and then stayed quiet for a few minutes; files_external keeps using the dead
client, on which every file looks missing. StorageBackend now checks the
connection after a minute without requests, and replaces a connection that
is dead after a failed request (once per request; put, move and delete are
not repeated). SftpReadStream closes a connection it left in an unknown state.

The verify cache refresh took more than 6 minutes on PostgreSQL for 27,547
packs, one autocommitted insert per pack: putMany()/replaceAll() write in one
transaction. After a verify the cache holds the index files as they are, so a
blob in two packs stays cached for both.
2026-10-12 01:58:54 +02:00
dillard d659322e60 Merge branch 'fix/sftp-fresh-connection' into polish 2026-10-11 17:16:33 +02:00
dillard df732f185a Index: refresh the cache after a verify in one pass over the blobs, not one per pack 2026-10-11 14:31:57 +02:00
dillard 379b81db02 Verify: index files several at a time over SFTP, pack folders listed, progress stored and shown 2026-10-11 13:39:38 +02:00
dillard 828f3f142a Merge branch 'fix/sftp-fresh-connection' into polish 2026-10-11 13:26:47 +02:00
dillard c146d700e8 Merge branch 'main' into polish 2026-10-11 13:25:06 +02:00
dillard 6385925845 Backup step: write the run only if no other process wrote it since it was loaded 2026-10-11 12:24:00 +02:00
dillard 894258f836 SFTP: open the channel before the first fast read; backup step: survive a takeover by another process 2026-10-11 11:45:27 +02:00
dillard fe92ef70bf Release 0.9.4-beta.5 2026-10-09 11:58:52 +02:00
dillard b3e3054737 SftpReadStream: fall back to the storage's own stream instead of failing a read 2026-10-09 11:24:37 +02:00
dillard c775e27dd2 CHANGELOG: SFTP reads with several requests in flight 2026-10-09 09:59:10 +02:00
dillard bcfec17cfe README: WebDAV request timeout on slow uploads; deep verify no longer fetches per blob 2026-10-08 22:38:32 +02:00
dillard 5f8d5faee7 Repository: read the blobs of a pack from one open stream
Restores and deep verifies requested every blob separately: a new file handle and a seek on
the location each time. They read the blobs of a snapshot in the order they were written, so
the stream of the pack read last now stays open and is read on; a jump backwards, to another
pack, or more than 8 MiB ahead opens the pack again at the offset, as before. On a Hetzner
Storage Box over SMB, restoring 86 MB in 202 files went from 0.78 MB/s to 4.2 MB/s.
2026-10-08 22:17:53 +02:00
dillard 65f14b4380 Merge branch 'main' into polish
# Conflicts:
#	CHANGELOG.md
2026-10-08 21:19:34 +02:00
dillard f4abfe0a8d Release 0.9.3-beta.4 2026-10-08 20:46:14 +02:00
dillard 466cff8857 CHANGELOG: fixes for the next hotfix 2026-10-08 18:28:29 +02:00
dillard a01aa16ccd Backups: show the progress of the files phase
A run only showed "running (files)", which says nothing during a backup
of a terabyte. The files phase now records an expected size on its first
step: the previous snapshot's size, or for a first backup the users'
files, versions and trash from Nextcloud's file cache (approximate, shown
with a ~). The web interface and occ backup:status show the share of it
done so far, including a large file that is still being read; it stays
below 100% until the run finishes.
2026-10-08 13:48:12 +02:00
dillard cc20b9174f info.xml: author e-mail address 2026-10-08 13:23:21 +02:00
dillard 9775cdc475 Locations: edit connection settings without losing the history
A changed password or host name could only be handled by adding a new
location, which starts an empty repository and, with a retention lock at
the provider, keeps the old one billed. Edit now changes a location in
place (web interface and occ backup:target:edit). The settings are only
saved when they lead to the same repository; a failed connection and a
missing repository give separate errors, and the folder is not created
while checking. Stored passwords are never sent to the browser: an empty
password field keeps the stored value.
2026-10-08 12:56:15 +02:00
dillard a8da8cb54a info.xml: website points to the GitHub repository
The app store shows <website> as the app's homepage; pointing it at the
store page itself made the link go nowhere.
2026-10-08 02:23:59 +02:00
dillard f415bab519 Verify, README: address review notes
An unreadable blob may still be a truncated pack, so don't rule out damage
in the verify message; README: Hetzner needs WebDAV/SMB and external
reachability enabled for the sub-account.
2026-10-08 01:11:21 +02:00
dillard 27eb0b32fc Release 0.9.2-beta.3 2026-10-08 01:00:52 +02:00
dillard fe7ad9b4b5 Verify: report read errors as unreadable, not as corrupted
verifyBlob() caught every exception from loading a blob and counted it as
a failed (corrupted or tampered) blob, so a transient network error during
a deep verify over WebDAV looked like data corruption. Read the range
separately, retry it, and report a read that keeps failing as unreadable
with its error; only a blob that was read but does not decrypt or match
its id counts as failed.
2026-10-08 00:53:31 +02:00
dillard 972a52e665 Settings: align the tabs with the sections
The tabs had no inline margin, so they sat against the edge while every
NcSettingsSection is inset by 7 grid baselines.
2026-10-08 00:47:47 +02:00
dillard 7c08a10621 Locations: ask for password confirmation before adding
addTarget requires a recent password confirmation, but the form never
asked for one. Within 30 minutes of logging in that went unnoticed; after
that, adding a location failed with a bare 403.
2026-10-08 00:40:48 +02:00
dillard 9554e774e5 CHANGELOG: correct why info.xml carries no -beta suffix 2026-10-07 18:01:20 +02:00
dillard 8b2dca28e3 Release 0.9.1-beta.2 2026-10-07 17:47:40 +02:00
dillard 5742f77253 App store listing: screenshots, links and UI fixes
Add three screenshots (backups, restore, settings) taken on a demo
instance, plus website, repository and the HOWTO as admin documentation
in info.xml.

Fixes found while taking them:
- the "new folder" restore option lost "<date>" (l10n sanitizes it as
  a tag); show the folder name pattern via a placeholder instead
- the restore-point dropdown cut off the time
- passphrase actions stacked vertically in the slot table
- HOWTO: SFTP example used "sftp::password", the auth mechanism is
  "password::password"
2026-10-07 17:43:41 +02:00
dillard 26cc9a897e Release 0.9.0-beta.1
Version 0.9.0 in info.xml, the app description for the beta, and the
CHANGELOG entry for 0.9.0-beta.1.
2026-10-07 01:07:55 +02:00
dillard 58711b67ef CHANGELOG: add the release link reference
CI / unit (8.2) (push) Has been cancelled
CI / unit (8.3) (push) Has been cancelled
CI / unit (8.4) (push) Has been cancelled
CI / psalm (push) Has been cancelled
CI / integration (mariadb, 32) (push) Has been cancelled
CI / integration (mariadb, 33) (push) Has been cancelled
CI / integration (mariadb, 34) (push) Has been cancelled
CI / integration (mariadb, 35) (push) Has been cancelled
CI / integration (pgsql, 32) (push) Has been cancelled
CI / integration (pgsql, 33) (push) Has been cancelled
CI / integration (pgsql, 34) (push) Has been cancelled
CI / integration (pgsql, 35) (push) Has been cancelled
CI / integration (sqlite, 32) (push) Has been cancelled
CI / integration (sqlite, 33) (push) Has been cancelled
CI / integration (sqlite, 34) (push) Has been cancelled
CI / integration (sqlite, 35) (push) Has been cancelled
CI / integration-targets (push) Has been cancelled
2026-10-05 12:17:10 +02:00
dillard e7229626f8 Prepare the 0.1.0-alpha.1 release
CI / unit (8.2) (push) Has been cancelled
CI / unit (8.3) (push) Has been cancelled
CI / unit (8.4) (push) Has been cancelled
CI / psalm (push) Has been cancelled
CI / integration (mariadb, 32) (push) Has been cancelled
CI / integration (mariadb, 33) (push) Has been cancelled
CI / integration (mariadb, 34) (push) Has been cancelled
CI / integration (mariadb, 35) (push) Has been cancelled
CI / integration (pgsql, 32) (push) Has been cancelled
CI / integration (pgsql, 33) (push) Has been cancelled
CI / integration (pgsql, 34) (push) Has been cancelled
CI / integration (pgsql, 35) (push) Has been cancelled
CI / integration (sqlite, 32) (push) Has been cancelled
CI / integration (sqlite, 33) (push) Has been cancelled
CI / integration (sqlite, 34) (push) Has been cancelled
CI / integration (sqlite, 35) (push) Has been cancelled
CI / integration-targets (push) Has been cancelled
info.xml's version field is restricted by Nextcloud's own info.xsd to plain
numeric SemVer, no pre-release suffix, so the alpha/beta/rc stage from
PLAN.md's release table lives in the git tag and CHANGELOG instead; noted
that in PLAN.md so it isn't rediscovered later. Bumped the version, wrote
an honest description for an alpha (feature-complete for phase 1, not for
production), and added CHANGELOG.md.

README: new "Storage backend experiences" section, seeded with the Hetzner
Storage Box sub-account root-path quirk found while testing a real SFTP
target (root must be "home", not "/"), open for others to extend via PR.
2026-10-05 11:45:48 +02:00