Optimize encryption, storage, and media streaming performance (#447)

- AES-256-GCM in-place decryption halves peak RAM in encrypted blob backend
- Offload crypto ≥64 KiB to spawn_blocking (unblocks async runtime)
- Fix off-by-one in encrypted range stream (end now exclusive)
- Collapse 3 DB round-trips for quota updates into 1 correlated UPDATE
- Set-based reconciliation sweep replaces per-user task spawning
- Eliminate entity re-read after file overwrite via RETURNING clause
- Lightbox streams video/photos inline instead of fetch→blob
This commit is contained in:
Dionisio Pozo
2026-06-10 14:53:55 +02:00
committed by GitHub
parent 26b396490c
commit fe0053bc79
10 changed files with 440 additions and 227 deletions
@@ -137,16 +137,19 @@ impl FileBlobWriteRepository {
/// removing the new blob reference.
///
/// `modified_at`: if `Some`, sets `updated_at` to that Unix timestamp;
/// if `None`, uses `NOW()` (server time). Returns the new hash on success.
/// if `None`, uses `NOW()` (server time). Returns
/// `(new_hash, updated_at_epoch)` on success — the effective timestamp
/// is returned so callers can rebuild the fresh entity without
/// re-reading the row.
async fn swap_blob_hash(
&self,
file_id: &str,
new_hash: &str,
new_size: i64,
modified_at: Option<i64>,
) -> Result<String, DomainError> {
) -> Result<(String, i64), DomainError> {
// Atomic CTE: capture old hash then update in one round-trip, no TOCTOU.
let old_hash = match sqlx::query_scalar::<_, String>(
let (old_hash, updated_at) = match sqlx::query_as::<_, (String, i64)>(
r#"
WITH old AS (
SELECT id, blob_hash FROM storage.files WHERE id = $3::uuid FOR UPDATE
@@ -156,7 +159,7 @@ impl FileBlobWriteRepository {
updated_at = COALESCE(to_timestamp($4), NOW())
FROM old
WHERE f.id = old.id
RETURNING old.blob_hash
RETURNING old.blob_hash, EXTRACT(EPOCH FROM f.updated_at)::bigint
"#,
)
.bind(new_hash)
@@ -166,7 +169,7 @@ impl FileBlobWriteRepository {
.fetch_optional(self.pool.as_ref())
.await
{
Ok(Some(old)) => old,
Ok(Some(row)) => row,
Ok(None) => {
// File not found — compensate: remove the new blob ref
if let Err(e) = self.dedup.remove_reference(new_hash).await {
@@ -201,7 +204,7 @@ impl FileBlobWriteRepository {
);
}
Ok(new_hash.to_string())
Ok((new_hash.to_string(), updated_at))
}
/// Like [`FileWritePort::save_file_from_temp`] but also returns whether the
@@ -513,7 +516,7 @@ impl FileWritePort for FileBlobWriteRepository {
content_type: Option<String>,
pre_computed_hash: Option<String>,
modified_at: Option<i64>,
) -> Result<String, DomainError> {
) -> Result<(String, i64), DomainError> {
// Streaming: pass pre-computed hash so dedup skips re-reading the file.
let dedup_result = self
.dedup