chore: update comments to reflect hash alg used (SHA-256 -> Blake3)
This commit is contained in:
@@ -78,7 +78,7 @@ Hexagonal / Clean Architecture with four layers. Dependencies point inward only.
|
|||||||
|
|
||||||
- **DI via `AppState`**: All services are `Arc`-wrapped and assembled in `common/di.rs`. `AppState` is wrapped in `Arc` and passed as Axum state. Many services are `Option<Arc<T>>` because they depend on features being enabled (auth, WOPI, trash, etc.).
|
- **DI via `AppState`**: All services are `Arc`-wrapped and assembled in `common/di.rs`. `AppState` is wrapped in `Arc` and passed as Axum state. Many services are `Option<Arc<T>>` because they depend on features being enabled (auth, WOPI, trash, etc.).
|
||||||
|
|
||||||
- **Content-addressable storage**: Files use SHA-256 blob dedup. `storage.file_blobs` stores content; `storage.file_metadata` references blobs with ref-counting. See `file_blob_write_repository.rs` and `file_blob_read_repository.rs`.
|
- **Content-addressable storage**: Files use BLAKE3 blob dedup. `storage.file_blobs` stores content; `storage.file_metadata` references blobs with ref-counting. See `file_blob_write_repository.rs` and `file_blob_read_repository.rs`.
|
||||||
|
|
||||||
- **ltree paths**: Folder hierarchy uses PostgreSQL `ltree` for efficient subtree queries (recursive copies, moves, searches).
|
- **ltree paths**: Folder hierarchy uses PostgreSQL `ltree` for efficient subtree queries (recursive copies, moves, searches).
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ OxiCloud uses **moka** (a lock-free, concurrent cache) for write-behind caching
|
|||||||
| Directory listings | 120 s | 10 000 | Frequently accessed folder contents |
|
| Directory listings | 120 s | 10 000 | Frequently accessed folder contents |
|
||||||
| Thumbnail cache | configurable | 1 000 | Generated WebP/AVIF thumbnails |
|
| Thumbnail cache | configurable | 1 000 | Generated WebP/AVIF thumbnails |
|
||||||
| Image transcode | configurable | 500 | On-the-fly image transcoding results |
|
| Image transcode | configurable | 500 | On-the-fly image transcoding results |
|
||||||
| Blob hash | 30 s TTI | 5 000 | SHA-256 hashes for dedup lookups |
|
| Blob hash | 30 s TTI | 5 000 | BLAKE3 hashes for dedup lookups |
|
||||||
| Audio metadata | — | 2 000 | ID3 tags and duration |
|
| Audio metadata | — | 2 000 | ID3 tags and duration |
|
||||||
|
|
||||||
## How It Works
|
## How It Works
|
||||||
|
|||||||
+2
-2
@@ -14,7 +14,7 @@ NextCloud was too slow on a home server. So OxiCloud was built to run on minimal
|
|||||||
| **Cold start** | < 1 s | 5–15 s |
|
| **Cold start** | < 1 s | 5–15 s |
|
||||||
| **CPU at idle** | ~0 % | 1–5 % (cron, background jobs) |
|
| **CPU at idle** | ~0 % | 1–5 % (cron, background jobs) |
|
||||||
| **Min. hardware** | 1 vCPU / 512 MB RAM | 2 vCPU / 2 GB RAM |
|
| **Min. hardware** | 1 vCPU / 512 MB RAM | 2 vCPU / 2 GB RAM |
|
||||||
| **File dedup** | SHA-256 content-addressable | None |
|
| **File dedup** | BLAKE3 content-addressable | None |
|
||||||
| **Dependencies** | Single binary + PostgreSQL | PHP, Apache/Nginx, Redis, Cron, … |
|
| **Dependencies** | Single binary + PostgreSQL | PHP, Apache/Nginx, Redis, Cron, … |
|
||||||
| **WebDAV** | Built-in (RFC 4918) | Built-in |
|
| **WebDAV** | Built-in (RFC 4918) | Built-in |
|
||||||
| **CalDAV / CardDAV** | Built-in | Via apps |
|
| **CalDAV / CardDAV** | Built-in | Via apps |
|
||||||
@@ -28,7 +28,7 @@ NextCloud was too slow on a home server. So OxiCloud was built to run on minimal
|
|||||||
### Storage & Files
|
### Storage & Files
|
||||||
- Drag-and-drop upload, multi-file, grid & list views
|
- Drag-and-drop upload, multi-file, grid & list views
|
||||||
- Chunked uploads (TUS-like, parallel, resumable, MD5 integrity)
|
- Chunked uploads (TUS-like, parallel, resumable, MD5 integrity)
|
||||||
- SHA-256 content-addressable file deduplication with ref-counting
|
- BLAKE3 content-addressable file deduplication with ref-counting
|
||||||
- Adaptive compression (zstd / gzip per MIME type)
|
- Adaptive compression (zstd / gzip per MIME type)
|
||||||
- Trash bin with soft-delete and auto-purge
|
- Trash bin with soft-delete and auto-purge
|
||||||
- Favourites, recent files, full-text search
|
- Favourites, recent files, full-text search
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ features:
|
|||||||
details: Single Rust binary, ~40 MB Docker image, <1s cold start, 30–50 MB idle RAM.
|
details: Single Rust binary, ~40 MB Docker image, <1s cold start, 30–50 MB idle RAM.
|
||||||
- icon: 📁
|
- icon: 📁
|
||||||
title: Full File Management
|
title: Full File Management
|
||||||
details: Chunked uploads, SHA-256 deduplication, trash, favourites, full-text search, thumbnails.
|
details: Chunked uploads, BLAKE3 deduplication, trash, favourites, full-text search, thumbnails.
|
||||||
- icon: 🔗
|
- icon: 🔗
|
||||||
title: WebDAV / CalDAV / CardDAV
|
title: WebDAV / CalDAV / CardDAV
|
||||||
details: RFC-compliant protocols for files, calendars, and contacts. Works with all major clients.
|
details: RFC-compliant protocols for files, calendars, and contacts. Works with all major clients.
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ type GlobalState = Arc<AppState>;
|
|||||||
pub struct HashCheckResponse {
|
pub struct HashCheckResponse {
|
||||||
/// Whether a blob with this hash already exists
|
/// Whether a blob with this hash already exists
|
||||||
pub exists: bool,
|
pub exists: bool,
|
||||||
/// The SHA-256 hash that was checked
|
/// The BLAKE3 hash that was checked
|
||||||
pub hash: String,
|
pub hash: String,
|
||||||
/// If exists, the size of the existing blob
|
/// If exists, the size of the existing blob
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
@@ -36,7 +36,7 @@ pub struct HashCheckResponse {
|
|||||||
pub struct DedupUploadResponse {
|
pub struct DedupUploadResponse {
|
||||||
/// Whether this was a new file or an existing one
|
/// Whether this was a new file or an existing one
|
||||||
pub is_new: bool,
|
pub is_new: bool,
|
||||||
/// The SHA-256 hash of the content
|
/// The BLAKE3 hash of the content
|
||||||
pub hash: String,
|
pub hash: String,
|
||||||
/// The size of the content in bytes
|
/// The size of the content in bytes
|
||||||
pub size: u64,
|
pub size: u64,
|
||||||
@@ -95,13 +95,13 @@ impl DedupHandler {
|
|||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let dedup = &state.core.dedup_service;
|
let dedup = &state.core.dedup_service;
|
||||||
|
|
||||||
// Validate hash format (SHA-256 = 64 hex chars)
|
// Validate hash format (BLAKE3 = 64 hex chars)
|
||||||
if hash.len() != 64 || !hash.chars().all(|c| c.is_ascii_hexdigit()) {
|
if hash.len() != 64 || !hash.chars().all(|c| c.is_ascii_hexdigit()) {
|
||||||
return Response::builder()
|
return Response::builder()
|
||||||
.status(StatusCode::BAD_REQUEST)
|
.status(StatusCode::BAD_REQUEST)
|
||||||
.header(header::CONTENT_TYPE, "application/json")
|
.header(header::CONTENT_TYPE, "application/json")
|
||||||
.body(Body::from(
|
.body(Body::from(
|
||||||
r#"{"error": "Invalid hash format. Expected SHA-256 (64 hex characters)"}"#,
|
r#"{"error": "Invalid hash format. Expected BLAKE3 (64 hex characters)"}"#,
|
||||||
))
|
))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into_response();
|
.into_response();
|
||||||
@@ -508,7 +508,7 @@ impl DedupHandler {
|
|||||||
get,
|
get,
|
||||||
path = "/api/dedup/check/{hash}",
|
path = "/api/dedup/check/{hash}",
|
||||||
params(
|
params(
|
||||||
("hash" = String, Path, description = "SHA-256 hash (64 hex characters)"),
|
("hash" = String, Path, description = "BLAKE3 hash (64 hex characters)"),
|
||||||
),
|
),
|
||||||
responses(
|
responses(
|
||||||
(status = 200, description = "Hash check result (user-scoped)", body = HashCheckResponse),
|
(status = 200, description = "Hash check result (user-scoped)", body = HashCheckResponse),
|
||||||
@@ -564,7 +564,7 @@ pub async fn get_stats(state: State<GlobalState>, auth_user: AuthUser) -> impl I
|
|||||||
get,
|
get,
|
||||||
path = "/api/dedup/blob/{hash}",
|
path = "/api/dedup/blob/{hash}",
|
||||||
params(
|
params(
|
||||||
("hash" = String, Path, description = "SHA-256 hash of the blob (64 hex characters)"),
|
("hash" = String, Path, description = "BLAKE3 hash of the blob (64 hex characters)"),
|
||||||
),
|
),
|
||||||
responses(
|
responses(
|
||||||
(status = 200, description = "Raw blob content (user-scoped)"),
|
(status = 200, description = "Raw blob content (user-scoped)"),
|
||||||
|
|||||||
Reference in New Issue
Block a user