Skip to content

Known Issues

Shelf cache design limitations by use case

This document summarizes known limitations of the current shelf cache behavior, based on the current implementation in shelf/shelf_cache.go, shelf/book.go, shelf/filestate.go, and shelf/shelf.go.

For the operational model, initial metadata scan, and tuning guidance, see Shelf Cache and Disk I/O.

If a change you made outside PlainShelf has not appeared, press Update book list on the library toolbar. It walks the shelf immediately instead of waiting for the next interval, and it is the same action in every setup below — local disk, SMB or NAS, a sync folder, a cloud mount, and the Android client's pCloud shelf. Every "may appear with delay" item on this page is bounded by it. See Rescanning on demand.


1) Desktop (single-machine usage)

  1. New books may appear with delay (up to scan_interval)
  2. Within scan_interval, refresh may only reopen books already in cache, instead of doing a full library scan.
  3. Newly added books from external file operations may not show up immediately.
  4. Update book list walks the shelf right away rather than waiting out the interval.

  5. Staleness detection is based only on book.json file stat (mtime + size)

  6. Content changes can be missed if they happen to preserve tracked stat values.

  7. Cache refresh decisions are driven by book.json

  8. Staleness checks focus on book.json, so metadata-derived cached book state can remain stale when only cover/source files change; this should not be interpreted as cover/source file contents themselves being cached.

2) Personal Tailscale (single server on one host, multiple personal clients)

Scope clarification: this scenario means one shelf server process running on one machine, with personal devices accessing that same server over Tailscale.

  1. No multi-server cache divergence in this mode
  2. Because there is only one server process, clients share one authoritative in-memory cache.

  3. Still has external file change visibility delay

  4. If the library folder is modified outside shelf (sync tool/manual operation), discovery is still bounded by refresh/full-scan behavior.
  5. Update book list discovers it immediately, from any client connected to that server.

  6. Staleness precision limitation still applies

  7. book.json stat-based validation can still miss certain edits.

3) Sync file app workflow (Dropbox/Google Drive/Syncthing/iCloud-like)

  1. Transient partial-sync states can cause temporary read/refresh failures
  2. During in-progress sync (rename/copy/write not complete), reopening a stale entry may fail and be skipped temporarily.

  3. Timestamp-preserving sync behavior can reduce change detectability

  4. If sync preserves/normalizes metadata and tracked stat values do not differ, stale detection may miss content-level changes.

  5. New/deleted books may not be reflected immediately

  6. During scan throttling windows, refresh focuses on existing cache entries.
  7. Update book list forces the walk once the sync has settled.

4) pCloud shelf on the Android client

  1. The book list never updates on its own
  2. Walking the shelf costs one recursive listing plus a request per book, so the client scans once and then reads the stored copy on the device. A book added, removed, or renamed from another device appears only after Update book list on the library toolbar.

  3. A stale list can make a book fail to open

  4. The stored copy holds the pCloud file references used to open a book. If the book was replaced or moved on pCloud since the last update, opening it fails until the list is updated. Downloaded books are unaffected — they are read from the device.

  5. Change detection is stat-based

  6. During an update, cached book metadata is reused while a file's size and modification time are unchanged, so an edit that preserves both is not noticed.

Concurrent change handling

PlainShelf is designed for single-user operation. Shelf-level structural operations (creating, moving, trashing, and restoring books) are serialized by a file lock, and every file write goes through an atomic temp-file-then-rename pattern, so a crash cannot leave a half-written file in the shelf. However, per-book mutations (editing metadata, changing covers, updating source content) are not individually serialized, which produces the following known behavior.

Last-writer-wins on the same book

When two requests modify the same book concurrently — for example, editing metadata in two browser tabs — both read the current book.json, apply their changes independently, and write the result back. The second write silently replaces the first, and the first edit's changes are lost without warning.

Each write stages through its own uniquely named temp file, so concurrent writers do not collide with each other and no request fails for that reason; the file left on disk is always one complete write. What is not guaranteed is that it contains both edits.

Affected operations: metadata updates, cover uploads/deletes, source content updates, and current-source selection.

Practical impact

For normal single-user, single-tab usage this limitation does not surface. It can matter when multiple browser tabs or clients edit the same book at the same time.

In that case the shelf directory remains structurally valid and every file is individually complete, but logical consistency across concurrent edits (no lost updates) is not guaranteed.


Notes

  • These are design trade-offs in the current cache strategy (scan throttling + per-book stale checks) and write-side concurrency model.
  • For personal Tailscale with one server, the main concerns are usually external folder mutations and scan interval tuning, not distributed cache coherence.