feat: real XMP sidecar adapter, replaces LogSidecarWriter stubs

- adapters-sidecar: XmpSidecarWriter using xmp_toolkit
- Writes StructuredData → XMP with EXIF/DC/XMP namespace routing
- Reads XMP back to StructuredData
- Wired into bootstrap + worker, deleted both LogSidecarWriter stubs
This commit is contained in:
2026-05-31 21:05:46 +02:00
parent d379f3d3c8
commit f85c0cb246
12 changed files with 304 additions and 53 deletions

View File

@@ -17,6 +17,7 @@ adapters-nats = { workspace = true }
adapters-event-transport = { workspace = true }
adapters-exif = { workspace = true }
adapters-thumbnail = { workspace = true }
adapters-sidecar = { workspace = true }
async-nats = { workspace = true }
futures = { workspace = true }

View File

@@ -41,7 +41,8 @@ async fn main() -> anyhow::Result<()> {
let file_storage = Arc::new(adapters_storage::LocalFileStorage::new(
&config.storage_path,
));
let sidecar_writer: Arc<dyn domain::ports::SidecarWriterPort> = Arc::new(LogSidecarWriter);
let sidecar_writer: Arc<dyn domain::ports::SidecarWriterPort> =
Arc::new(adapters_sidecar::XmpSidecarWriter);
// Publisher transport consumes a client clone; the consumer gets another.
let pub_transport = adapters_nats::NatsTransport::new(nats_client.clone());
@@ -168,29 +169,3 @@ async fn main() -> anyhow::Result<()> {
error!("event loop: NATS stream ended unexpectedly");
Ok(())
}
struct LogSidecarWriter;
#[async_trait::async_trait]
impl domain::ports::SidecarWriterPort for LogSidecarWriter {
fn format_name(&self) -> &str {
"log_noop"
}
async fn write_sidecar(
&self,
_data: &domain::value_objects::StructuredData,
path: &str,
) -> Result<(), domain::errors::DomainError> {
info!(path, "sidecar write (no-op)");
Ok(())
}
async fn read_sidecar(
&self,
path: &str,
) -> Result<domain::value_objects::StructuredData, domain::errors::DomainError> {
info!(path, "sidecar read (no-op)");
Ok(domain::value_objects::StructuredData::new())
}
}