diff options
Diffstat (limited to 'DESIGN.md')
| -rw-r--r-- | DESIGN.md | 25 |
1 files changed, 21 insertions, 4 deletions
@@ -163,6 +163,7 @@ used. The file is written atomically (write to a `.tmp` file, then | `visible` | `true` | If `false`, hidden from non-admin visitors | | `taken_at` | `null` | ISO 8601 timestamp from EXIF; used for chronological sorting | | `width` / `height` | `null` | Pixel dimensions recorded by `update.rb` | +| `exif_absent` | `null` | Set to `true` by `update.rb` when exiftool found no metadata; skips re-extraction on future rescans | When `taken_at` is present on *any* file in an album, the entire album is sorted chronologically. Albums with no `taken_at` data stay in filename @@ -342,17 +343,31 @@ Run this after copying new media files onto the server. It is safe to re-run at any time — all operations are idempotent. ```bash -ruby /opt/albumen/scripts/update.rb [optional/subdir] +ruby /opt/albumen/scripts/update.rb # full tree, skip unchanged dirs +ruby /opt/albumen/scripts/update.rb 2024-Italy # explicit subtree, always runs +ruby /opt/albumen/scripts/update.rb --force # full tree, ignore all sentinels ``` -**What it does, per directory:** +**Change detection** — each directory gets a `.albumen_scanned` sentinel file +whose mtime is set at the end of a successful scan. On subsequent runs the +script compares `sentinel.mtime >= dir.mtime`: if true the directory is skipped +entirely (no file I/O). A global run with nothing new completes in well under a +second regardless of library size. + +Providing an explicit subdirectory argument bypasses the sentinel for that +subtree, so `update.rb some-album` always rescans that album even if the +directory mtime appears unchanged. `--force` bypasses sentinels for the whole +tree. + +**What it does, per directory (when not skipped):** 1. Reads the existing `album.json` (or starts from defaults). -2. Removes stale `files` entries for deleted files. +2. Removes stale `files` entries for deleted files (and their thumbnails). 3. For each media file: - **Images:** reads EXIF `DateTimeOriginal` (or `CreateDate`) and stores it as `taken_at`; reads pixel dimensions. Both are skipped if already - recorded. + recorded. If exiftool finds no metadata at all, sets `exif_absent: true` + so the tool is not re-invoked on future rescans of that file. - **Videos:** runs `ffprobe` to record duration. Skipped if already recorded. - **All non-audio:** generates a thumbnail if one doesn't already exist. @@ -361,6 +376,8 @@ ruby /opt/albumen/scripts/update.rb [optional/subdir] fields (`title`, `description`, `cover`, `sort_reverse`, `visible`, per-file `title`/`caption`/`visible`). 5. Writes the updated JSON atomically. +6. Touches the `.albumen_scanned` sentinel so the next global run skips + this directory. **Ownership:** When run as root (the typical case after an rsync), the script calls `FileUtils.chown_R` to transfer ownership of the media tree |
