Treat a placeholder as the photograph, not as a one-byte file
The folder connector was pointed at a Nextcloud VFS tree and got three things wrong, the first of which loses work. **A dehydrated sidecar read as absent.** `a.drsc` does not exist when the client has dehydrated it — only `a.drsc.nextcloud` does — so `get` missed, `.ok()` swallowed the `NotFound`, and the sidecar writer took that for "there is no sidecar yet" and wrote a fresh document over the existing one. Every edit another device had put there went with it. That function's own doc comment calls this the exact loss the format's unknown-key preservation exists to prevent. **A stub was catalogued as a 1-byte image**, and ARCH §9.0 measured this machine at 121,785 placeholders against 10,267 real files — so a folder library on a synced tree was ~92% broken rows. **Identity changed on hydration**, so downloading a photograph looked like a delete and an add, orphaning its thumbnail and its face rows. Entries now carry the photograph's own name and a `materialised` flag; `get` on a stub returns the new `RemoteError::NotMaterialised`, which is distinct from `NotFound` precisely because the sidecar writer must treat them differently — it fetches the sidecar and merges, or leaves the entry queued. Hydration is a **borrow**. `BorrowPool` records what was on disk before it asked, so `release_all` dehydrates only what a pass brought and leaves what the user already had. Reference counted: the thumbnail pass and the face pass meet on the same RAW, and without counting the first to finish dehydrates the file the second is reading. A borrow against a plain folder or a server does nothing, so a pass written for VFS runs everywhere. Releasing means asking the client to dehydrate and never deleting: a deletion inside a synced tree propagates to the server and removes the photograph from every device. Not a second backend — the capability is per *connection*, not per type, since the same folder hydrates only while the client runs. The convention arrives through a detector the registry supplies, so `dr-sync-folder` still knows nothing about any client's protocol. ARCH §9.0a records this as an amendment: finding 3 rejected hydration because it costs 100× a range read, and that comparison assumed a connector was available. A folder library has none.
This commit is contained in:
+11
-2
@@ -25,7 +25,7 @@ use std::sync::{Arc, OnceLock};
|
||||
|
||||
use dr_sync::{Account, BackendProvider, BackendRegistry, Connection, RemoteBackend, RemoteError};
|
||||
use dr_sync_folder::FolderProvider;
|
||||
use dr_sync_nextcloud::NextcloudProvider;
|
||||
use dr_sync_nextcloud::{NextcloudProvider, NextcloudVfs};
|
||||
|
||||
/// Every storage backend this build has, in the order the launch screen
|
||||
/// offers them.
|
||||
@@ -37,7 +37,16 @@ pub fn registry() -> &'static BackendRegistry {
|
||||
REGISTRY.get_or_init(|| {
|
||||
let mut r = BackendRegistry::new();
|
||||
r.register(Arc::new(NextcloudProvider));
|
||||
r.register(Arc::new(FolderProvider));
|
||||
// TRACES: FR-NC-6c
|
||||
// The folder connector does the filesystem work and knows nothing
|
||||
// about sync clients; the placeholder convention is supplied here,
|
||||
// which is the one place that may name one. Detection is per folder
|
||||
// and per connection — the same directory offers hydration while the
|
||||
// client is running and not while it is down (ARCH §9.0).
|
||||
r.register(Arc::new(FolderProvider::with_vfs_detector(|root| {
|
||||
NextcloudVfs::looks_synced(root)
|
||||
.then(|| Arc::new(NextcloudVfs::detect()) as Arc<dyn dr_sync_folder::Vfs>)
|
||||
})));
|
||||
r
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user