perf(dav-collections): indexed UID lookups for single-object operations
Every CalDAV PUT/GET/DELETE of one .ics loaded the ENTIRE calendar — every row including its ical_data — and filtered with .find() in Rust, so importing N events cost O(N²) rows transferred. CardDAV did the exact same in four places (PROPFIND of one .vcf, PUT existence check, GET, DELETE), with three JSONB deserializations per discarded contact. The indexed repo queries (find_event_by_ical_uid, get_contact_by_uid) existed all along with zero callers. Wire them end to end: new `get_event_by_ical_uid` / `get_contact_by_uid` use-case methods (same access checks as list_events / list_contacts, per the service-layer authz rule) exposed through the storage ports and adapters, and the seven handler sites now resolve one row instead of the whole collection. https://claude.ai/code/session_01Dp3oWon5GBMVn4j3QXZdgx
This commit is contained in:
@@ -402,6 +402,26 @@ impl CalendarStoragePort for CalendarStorageAdapter {
|
||||
Ok(CalendarEventDto::from(event))
|
||||
}
|
||||
|
||||
async fn find_event_by_ical_uid(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
ical_uid: &str,
|
||||
) -> Result<Option<CalendarEventDto>, DomainError> {
|
||||
let uuid = Uuid::parse_str(calendar_id).map_err(|_| {
|
||||
DomainError::new(
|
||||
ErrorKind::InvalidInput,
|
||||
"Calendar",
|
||||
"Invalid calendar ID format",
|
||||
)
|
||||
})?;
|
||||
|
||||
let event = self
|
||||
.event_repository
|
||||
.find_event_by_ical_uid(&uuid, ical_uid)
|
||||
.await?;
|
||||
Ok(event.map(CalendarEventDto::from))
|
||||
}
|
||||
|
||||
async fn list_events_by_calendar(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
|
||||
@@ -712,6 +712,24 @@ impl ContactUseCase for ContactStorageAdapter {
|
||||
Ok(ContactDto::from(contact))
|
||||
}
|
||||
|
||||
async fn get_contact_by_uid(
|
||||
&self,
|
||||
address_book_id: &str,
|
||||
uid: &str,
|
||||
user_id: Uuid,
|
||||
) -> Result<Option<ContactDto>, DomainError> {
|
||||
let uuid = Self::parse_uuid(address_book_id, "AddressBook")?;
|
||||
|
||||
// Check read access
|
||||
self.check_address_book_access(&uuid, user_id).await?;
|
||||
|
||||
let contact = self
|
||||
.contact_repository
|
||||
.get_contact_by_uid(&uuid, uid)
|
||||
.await?;
|
||||
Ok(contact.map(ContactDto::from))
|
||||
}
|
||||
|
||||
async fn list_contacts(
|
||||
&self,
|
||||
address_book_id: &str,
|
||||
|
||||
Reference in New Issue
Block a user