8000 feat(backups): restore, download, any schedule and copies to an rclone connection from the web app by adeelahmad · Pull Request #263 · adeelahmad/lense · GitHub
[go: up one dir, main page]

Skip to content

feat(backups): restore, download, any schedule and copies to an rclone connection from the web app - #263

Merged
adeelahmad merged 5 commits into
mainfrom
claude/project-thread-rj1jwj
Oct 10, 2026
Merged

adeelahmad merged 5 commits into
mainfrom
claude/project-thread-rj1jwj

Conversation

@adeelahmad
@adeelahmad adeelahmad commented Oct 10, 2026 •
Copy link
Copy Markdown
Owner

Requested by Adeel · project thread

Description

Before: backups could be listed, taken, downloaded (exports only) and deleted through /admin/backups. Putting one back meant surreal import or swapping folders by hand, nothing took backups on a schedule, and every copy stayed on the same machine.

After: Settings › Backups lists every backup with Back up now, Download, Restore and Delete. The schedule is fully configurable: off, presets (nightly, every 6 hours, hourly, weekly) or any cron, with a timezone and how many to keep. Backups can also go to a storage connection (any rclone remote from Settings › Sources), sealed with AES-256-GCM under a key derived from secret.key before they leave the machine. Scheduled and manual backups are copied there, and a copy that only exists on the connection can be brought back and restored. Restoring replaces the whole database: what was there is backed up first (before-restore-*) and put back if the restore fails, and a backup from an older Lens is brought up to date afterwards. Downloads use a two-minute signed link; an embedded database's folder downloads as a .tar.gz.

How: app/domain/backups.py gains restore (server: REMOVE DATABASE/DEFINE DATABASE then /import; embedded: folder swap under db.closed()), run_due (routine scheduler, processes take turns via backup_schedule:next), and seal/unseal/send/fetch using the rclone helpers in blobs.py. db.closed() now keeps the pool places taken, so a query that arrives during an embedded restore waits instead of opening the files again, and it waits until the engine has let go of them. New routes are POST /admin/backups/{name}/restore|link|send|fetch, GET /admin/backups/{name}/file, GET /admin/backups/remote and DELETE /admin/backups/{name}/remote. Restore and links need an admin signed in with a passkey. New settings are backups.schedule, timezone, keep (7), connection and folder.

Motivation and Context

Adeel asked for backup and restore end to end from the web app, then for configurable scheduled backups and remote backups through an rclone remote. The one-click upgrade can call backups.restore for its rollback.

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; ! in the title)

Checklist:

  • The title is a Conventional Commit.
  • My code follows the code style of this project (make hooks checks it on commit).
  • I added or updated tests. tests/api/test_backups.py covers embedded and a SurrealDB 3.2.4 server; the rclone tests run where rclone is installed.
  • My change requires documentation updates, and I have updated docs/ accordingly (docs/database.md#backups).
  • Users need more than the title to understand it, so I wrote it under ## Unreleased in CHANGELOG.md.

🤖 Generated with Claude Code

https://claude.ai/code/session_012qkVq3xnW9YJboxRYV4qSv

… machine agent

Lens checks GitHub for a new release once a day, backs the database up and
installs a release from the API: install.sh sets up a small agent on the
machine (systemd path unit on Linux, launchd on a Mac) that watches
.lens-control/inbox, reruns install.sh for the requested release and writes
how it went back for the web app. Backups can be listed, taken, downloaded
and deleted. __version__ now follows releases.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XturGhybJzfgZvbFxfNB2o
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XturGhybJzfgZvbFxfNB2o
… web app

Builds on the backups list from the updates work: restoring a backup replaces the
database (server: remove and import; embedded: folder swap), with a before-restore
backup put back if it fails, then the schema, upgrades and settings reload.
Downloads go through a two-minute signed link (embedded folders as .tar.gz).
backups.schedule/timezone/keep take scheduled backups from the routine scheduler.
Settings > Backups lists them with Back up now, Download, Restore and Delete.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012qkVq3xnW9YJboxRYV4qSv
@adeelahmad adeelahmad self-assigned this Oct 10, 2026
Base automatically changed from claude/project-thread-k36y5e to main October 10, 2026 19:53
- Settings > Backups: any cron schedule (presets or custom), timezone, how many to keep
- Backups go to an rclone storage connection, sealed with secret.key before they leave
- Bring a backup back from the connection, then restore it
- Embedded restore: queries meanwhile wait for the pool instead of reopening the files

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012qkVq3xnW9YJboxRYV4qSv
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012qkVq3xnW9YJboxRYV4qSv
@adeelahmad adeelahmad changed the title feat(backups): restore, download links and scheduled backups from the web app feat(backups): restore, download, any schedule and copies to an rclone connection from the web app Oct 10, 2026
@adeelahmad
adeelahmad merged commit c8f71f0 into main Oct 10, 2026
8 checks passed
@adeelahmad
adeelahmad deleted the claude/project-thread-rj1jwj branch October 10, 2026 21:11
adeelahmad pushed a commit that referenced this pull request Oct 10, 2026
updates.restore_on_start now checks the backup with backups.usable and restores it with backups.restore (which takes
a before-restore backup, re-applies the schema and reloads settings); migrations.restore and _import are gone. The
Updates page links to Settings → Backups instead of listing backups itself.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FZXPL8F3sAdGJKYYgrVHxb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

0