Let the interface hold a backend without knowing whose it is
`dr-sync` defines `RemoteBackend` and a capability model the engine adapts to, so a second backend can be added without touching the code that uses one. That boundary was documentation. Seven files in `dr-ui` constructed a `NextcloudBackend` directly, ten functions took one by concrete type, and exactly two call sites in the tree — both inside `dr-sync` itself — ever held the trait object. A WebDAV or local-folder backend would have had a well-written trait to implement and nowhere to go afterwards. The change is smaller than the finding suggests, because the trait was already right. Every method the UI has ever called on a backend — `get`, `put`, `list`, `delete`, `create_dir`, `move_to` — was already on it, so nothing had to be added and no behaviour moved. Ten signatures widened to `&dyn RemoteBackend`, sixteen constructions became `remote::connect`, and `remote.rs` is now the only file in the interface that names a connector. `connect` returns `Result<Box<dyn RemoteBackend>, RemoteError>`. The error type is `dr-sync`'s rather than the connector's, which is why every call site kept its shape — the `match`, the `let Ok(..) else`, and `.map_err(ScanFailure::local)?` all still read as they did. One wrinkle worth recording: `&Box<dyn Trait>` does not reach `&dyn Trait` on its own. The compiler reaches for unsizing, which wants `Box<dyn RemoteBackend>: RemoteBackend`, and reports a confusing missing impl rather than suggesting a deref. Twelve call sites therefore say `&*backend`, and two say `let backend: &dyn RemoteBackend = &*backend` where a borrow is shared across lanes. What this does *not* do is abstract credentials. `AppCredentials` is an app password from Login Flow v2 — a Nextcloud protocol, not a general notion of authenticating to a remote — and seven files still name it. An OAuth token, a bucket key pair and an app password have no useful common shape, so deciding what an account is across backends before a second one exists would be a confident guess. code-health.md CH-2 now records that as the remaining half, and it should wait for the backend that forces it. Verified: fmt clean, clippy clean at -D warnings, 2041 tests pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -56,7 +56,7 @@ use std::sync::Arc;
|
||||
use dr_ingest::{Candidate, DupKey, Imported, Ingest, Options, Report, Shot, TransferMode};
|
||||
use dr_plat::{DirRef, LocalStorage, Storage, WritableStorage};
|
||||
use dr_sync::{RemoteBackend, RemotePath};
|
||||
use dr_sync_nextcloud::{AppCredentials, NextcloudBackend};
|
||||
use dr_sync_nextcloud::AppCredentials;
|
||||
use dr_types::{FormatFilter, RootId};
|
||||
|
||||
/// Which root the card is granted as, and which the library is.
|
||||
@@ -385,7 +385,7 @@ fn upload_all(
|
||||
};
|
||||
|
||||
rt.block_on(async {
|
||||
let backend = match NextcloudBackend::new(&upload.credentials, &upload.user_id) {
|
||||
let backend = match crate::remote::connect(&upload.credentials, &upload.user_id) {
|
||||
Ok(b) => b,
|
||||
Err(e) => {
|
||||
log::warn!("connecting to upload: {e}");
|
||||
@@ -423,7 +423,7 @@ fn upload_all(
|
||||
|
||||
// The same folder segments the local copy went into, so the two
|
||||
// libraries have the same shape (FR-NC-7a).
|
||||
match dr_sync::upload_original(&backend, &root, &image.folders, &image.name, bytes)
|
||||
match dr_sync::upload_original(&*backend, &root, &image.folders, &image.name, bytes)
|
||||
.await
|
||||
{
|
||||
Ok(placed) => {
|
||||
@@ -445,7 +445,7 @@ fn upload_all(
|
||||
Err(e) => log::warn!("uploading {}: {e}", image.name),
|
||||
}
|
||||
}
|
||||
let filed = file_thumbnails(&backend, &root, imported, &sent, &upload.thumbs).await;
|
||||
let filed = file_thumbnails(&*backend, &root, imported, &sent, &upload.thumbs).await;
|
||||
(sent, filed)
|
||||
})
|
||||
}
|
||||
@@ -502,7 +502,7 @@ fn make_thumbnail(bytes: &[u8]) -> Option<dr_thumbs::Thumbnail> {
|
||||
/// Best-effort throughout. A thumbnail that cannot be filed costs the grid one
|
||||
/// preview fetch later; failing the import over it would be the wrong trade.
|
||||
async fn file_thumbnails(
|
||||
backend: &NextcloudBackend,
|
||||
backend: &dyn RemoteBackend,
|
||||
library: &RemotePath,
|
||||
imported: &[Imported],
|
||||
sent: &[Sent],
|
||||
|
||||
Reference in New Issue
Block a user