Two deployment bugs that both present as "the client says done but the markdown never changes, and nothing errors". 1. upload() diffed the client's VTODO against the cached in-memory task. When that cache disagreed with disk the diff came out empty, apply() returned early, and Radicale answered 2xx having written nothing. The cache goes stale on NFS: refresh_if_stale() compares stat(), and a `- [ ]` to `- [x]` toggle does not change the file's size, so mtime is the only signal — which NFS attribute caching hides for the length of the attr timeout. Add Index.refresh_file(), which compares the actual bytes, and call it before diffing. 2. docker/mdcaldav.toml set `exclude`, which REPLACES the built-in list rather than extending it, silently dropping the Syncthing patterns. Against a real Syncthing vault this reindexes `*.sync-conflict-*` (and `.stversions/`, which holds whole historical copies of every note): the task list gains duplicates, and completing one can write to a conflict file the user never opens while the note they are watching stays put. Drop the override so the defaults apply. Also switch the container to a polling observer. inotify reports nothing for a network mount written by another host, so `watch = true` was a silent no-op exactly where it was most wanted. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
36 lines
1.4 KiB
TOML
36 lines
1.4 KiB
TOML
[vault]
|
|
path = "/vault"
|
|
include = ["**/*.md"]
|
|
# `exclude` is deliberately not set: setting it REPLACES the built-in list,
|
|
# which is where the Syncthing patterns live (`.stversions/**`, which holds
|
|
# whole historical copies of your notes, and `*.sync-conflict-*`). Overriding
|
|
# it with just the VCS/editor globs silently reindexes both — you get duplicate
|
|
# tasks, and a completion can land in a conflict file you never open while the
|
|
# note you are actually looking at stays unchanged.
|
|
# To add your own, restate the defaults from config.DEFAULT_EXCLUDE too.
|
|
# Keeps the index warm off the request path. Purely a latency optimization:
|
|
# every read path calls refresh_if_stale(), so freshness does not depend on it.
|
|
watch = true
|
|
# Poll rather than wait on inotify. A containerized vault is usually a bind
|
|
# mount, and often a network one (NFS, CIFS) — inotify reports nothing at all
|
|
# for changes written by another host, so the watcher would sit silent. Set to
|
|
# 0 to use inotify when the vault is genuinely local.
|
|
poll_interval = 2.0
|
|
|
|
[collections]
|
|
group_by = "directory"
|
|
depth = 1
|
|
|
|
[write]
|
|
allow_create = true
|
|
allow_delete = true
|
|
inbox = "inbox.md"
|
|
inbox_heading = "## Inbox"
|
|
delete_children = "cascade"
|
|
# Recommended until you trust write-back. Kept outside the vault.
|
|
backup_dir = "/data/backups"
|
|
|
|
[index]
|
|
# Must NOT live inside /vault — it is a derived cache, not a note.
|
|
db = "/data/index.db"
|