diff --git a/.sqlx/query-dd1b61d6ec81fd891d4effd3b51e6c22308b878acdc5355dfcb04c5664c9463b.json b/.sqlx/query-03f129e4984e1bed9e87294adc9caf1730906d889101b9039113ec8aa234618d.json
similarity index 84%
rename from .sqlx/query-dd1b61d6ec81fd891d4effd3b51e6c22308b878acdc5355dfcb04c5664c9463b.json
rename to .sqlx/query-03f129e4984e1bed9e87294adc9caf1730906d889101b9039113ec8aa234618d.json
index 236230f..910d998 100644
--- a/.sqlx/query-dd1b61d6ec81fd891d4effd3b51e6c22308b878acdc5355dfcb04c5664c9463b.json
+++ b/.sqlx/query-03f129e4984e1bed9e87294adc9caf1730906d889101b9039113ec8aa234618d.json
@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
- "query": "SELECT storage_key, mime_type, size_bytes FROM blobs WHERE cid = $1",
+ "query": "SELECT storage_key, mime_type, size_bytes FROM blobs WHERE cid = $1 LIMIT 1",
"describe": {
"columns": [
{
@@ -30,5 +30,5 @@
false
]
},
- "hash": "dd1b61d6ec81fd891d4effd3b51e6c22308b878acdc5355dfcb04c5664c9463b"
+ "hash": "03f129e4984e1bed9e87294adc9caf1730906d889101b9039113ec8aa234618d"
}
diff --git a/.sqlx/query-0890b2c7c921005f58ed0e57b6e062b2085ce804a4cccb27b4ae2ba6711f24c4.json b/.sqlx/query-155efbae4cd55f73ec0709dda7b18a76e92065e6ae4a6081bd38a19821fbfcc3.json
similarity index 67%
rename from .sqlx/query-0890b2c7c921005f58ed0e57b6e062b2085ce804a4cccb27b4ae2ba6711f24c4.json
rename to .sqlx/query-155efbae4cd55f73ec0709dda7b18a76e92065e6ae4a6081bd38a19821fbfcc3.json
index 14db6c2..3f02003 100644
--- a/.sqlx/query-0890b2c7c921005f58ed0e57b6e062b2085ce804a4cccb27b4ae2ba6711f24c4.json
+++ b/.sqlx/query-155efbae4cd55f73ec0709dda7b18a76e92065e6ae4a6081bd38a19821fbfcc3.json
@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
- "query": "SELECT COALESCE(SUM(size_bytes), 0)::BIGINT as \"total!\" FROM blobs",
+ "query": "SELECT COALESCE(SUM(size_bytes), 0)::BIGINT as \"total!\"\n FROM (SELECT DISTINCT cid, size_bytes FROM blobs) t",
"describe": {
"columns": [
{
@@ -16,5 +16,5 @@
null
]
},
- "hash": "0890b2c7c921005f58ed0e57b6e062b2085ce804a4cccb27b4ae2ba6711f24c4"
+ "hash": "155efbae4cd55f73ec0709dda7b18a76e92065e6ae4a6081bd38a19821fbfcc3"
}
diff --git a/.sqlx/query-62942bd21d545eb15bfea4f46378b6c2ebfe12b8bc9e27c63a6c0f77a9105303.json b/.sqlx/query-5996484ff0f8dbc3b278cfd01b8375dbf7bf6da8d903145b12871dda6e1fd5d9.json
similarity index 67%
rename from .sqlx/query-62942bd21d545eb15bfea4f46378b6c2ebfe12b8bc9e27c63a6c0f77a9105303.json
rename to .sqlx/query-5996484ff0f8dbc3b278cfd01b8375dbf7bf6da8d903145b12871dda6e1fd5d9.json
index f3ae0be..df39367 100644
--- a/.sqlx/query-62942bd21d545eb15bfea4f46378b6c2ebfe12b8bc9e27c63a6c0f77a9105303.json
+++ b/.sqlx/query-5996484ff0f8dbc3b278cfd01b8375dbf7bf6da8d903145b12871dda6e1fd5d9.json
@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
- "query": "SELECT cid, takedown_ref FROM blobs WHERE cid = $1",
+ "query": "SELECT cid, takedown_ref FROM blobs WHERE cid = $1 ORDER BY takedown_ref NULLS LAST LIMIT 1",
"describe": {
"columns": [
{
@@ -24,5 +24,5 @@
true
]
},
- "hash": "62942bd21d545eb15bfea4f46378b6c2ebfe12b8bc9e27c63a6c0f77a9105303"
+ "hash": "5996484ff0f8dbc3b278cfd01b8375dbf7bf6da8d903145b12871dda6e1fd5d9"
}
diff --git a/.sqlx/query-8844d942ef2810afc386e5a9838624ee07a43c380d2df31efdba5cf299aab571.json b/.sqlx/query-8844d942ef2810afc386e5a9838624ee07a43c380d2df31efdba5cf299aab571.json
new file mode 100644
index 0000000..dfc4e45
--- /dev/null
+++ b/.sqlx/query-8844d942ef2810afc386e5a9838624ee07a43c380d2df31efdba5cf299aab571.json
@@ -0,0 +1,22 @@
+{
+ "db_name": "PostgreSQL",
+ "query": "SELECT storage_key as \"storage_key!\" FROM blobs b\n WHERE created_by_user = $1\n AND NOT EXISTS (\n SELECT 1 FROM blobs o\n WHERE o.cid = b.cid AND o.created_by_user <> $1\n )",
+ "describe": {
+ "columns": [
+ {
+ "ordinal": 0,
+ "name": "storage_key!",
+ "type_info": "Text"
+ }
+ ],
+ "parameters": {
+ "Left": [
+ "Uuid"
+ ]
+ },
+ "nullable": [
+ false
+ ]
+ },
+ "hash": "8844d942ef2810afc386e5a9838624ee07a43c380d2df31efdba5cf299aab571"
+}
diff --git a/.sqlx/query-8afea2b745385348f4c78b51f74145d6718bfcf9a3a0c218109ec691aeb930ba.json b/.sqlx/query-996e5513fb55670fe3304a6046381e377da6a187dfa3347bd285078a7b4410f2.json
similarity index 74%
rename from .sqlx/query-8afea2b745385348f4c78b51f74145d6718bfcf9a3a0c218109ec691aeb930ba.json
rename to .sqlx/query-996e5513fb55670fe3304a6046381e377da6a187dfa3347bd285078a7b4410f2.json
index 026d3ff..7857cc0 100644
--- a/.sqlx/query-8afea2b745385348f4c78b51f74145d6718bfcf9a3a0c218109ec691aeb930ba.json
+++ b/.sqlx/query-996e5513fb55670fe3304a6046381e377da6a187dfa3347bd285078a7b4410f2.json
@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
- "query": "INSERT INTO blobs (cid, mime_type, size_bytes, created_by_user, storage_key)\n VALUES ($1, $2, $3, $4, $5)\n ON CONFLICT (cid) DO NOTHING RETURNING cid",
+ "query": "INSERT INTO blobs (cid, mime_type, size_bytes, created_by_user, storage_key)\n VALUES ($1, $2, $3, $4, $5)\n ON CONFLICT (cid, created_by_user) DO NOTHING RETURNING cid",
"describe": {
"columns": [
{
@@ -22,5 +22,5 @@
false
]
},
- "hash": "8afea2b745385348f4c78b51f74145d6718bfcf9a3a0c218109ec691aeb930ba"
+ "hash": "996e5513fb55670fe3304a6046381e377da6a187dfa3347bd285078a7b4410f2"
}
diff --git a/.sqlx/query-6131bb5b39ca81bdbb193c0a9867bead8d9f3d793ad4eca97a79d166467a5052.json b/.sqlx/query-9fb9e128076b20ff067d01955221488ce7e5b886dba0529fb073c3e0461fe030.json
similarity index 65%
rename from .sqlx/query-6131bb5b39ca81bdbb193c0a9867bead8d9f3d793ad4eca97a79d166467a5052.json
rename to .sqlx/query-9fb9e128076b20ff067d01955221488ce7e5b886dba0529fb073c3e0461fe030.json
index 5c07cbf..d05f896 100644
--- a/.sqlx/query-6131bb5b39ca81bdbb193c0a9867bead8d9f3d793ad4eca97a79d166467a5052.json
+++ b/.sqlx/query-9fb9e128076b20ff067d01955221488ce7e5b886dba0529fb073c3e0461fe030.json
@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
- "query": "SELECT storage_key FROM blobs WHERE cid = $1",
+ "query": "SELECT storage_key FROM blobs WHERE cid = $1 LIMIT 1",
"describe": {
"columns": [
{
@@ -18,5 +18,5 @@
false
]
},
- "hash": "6131bb5b39ca81bdbb193c0a9867bead8d9f3d793ad4eca97a79d166467a5052"
+ "hash": "9fb9e128076b20ff067d01955221488ce7e5b886dba0529fb073c3e0461fe030"
}
diff --git a/.sqlx/query-f59010ecdd7f782489e0e03288a06dacd72b33d04c1e2b98475018ad25485852.json b/.sqlx/query-f59010ecdd7f782489e0e03288a06dacd72b33d04c1e2b98475018ad25485852.json
deleted file mode 100644
index 218f7cd..0000000
--- a/.sqlx/query-f59010ecdd7f782489e0e03288a06dacd72b33d04c1e2b98475018ad25485852.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "db_name": "PostgreSQL",
- "query": "SELECT storage_key as \"storage_key!\" FROM blobs WHERE created_by_user = $1",
- "describe": {
- "columns": [
- {
- "ordinal": 0,
- "name": "storage_key!",
- "type_info": "Text"
- }
- ],
- "parameters": {
- "Left": [
- "Uuid"
- ]
- },
- "nullable": [
- false
- ]
- },
- "hash": "f59010ecdd7f782489e0e03288a06dacd72b33d04c1e2b98475018ad25485852"
-}
diff --git a/crates/tranquil-api/src/repo/blob.rs b/crates/tranquil-api/src/repo/blob.rs
index aa0f7b1..1e2df0f 100644
--- a/crates/tranquil-api/src/repo/blob.rs
+++ b/crates/tranquil-api/src/repo/blob.rs
@@ -148,7 +148,13 @@ pub async fn upload_blob(
size, cid_str
);
- match state
+ if let Err(e) = state.blob_store.copy(&temp_key, &storage_key).await {
+ let _ = state.blob_store.delete(&temp_key).await;
+ error!("Failed to copy blob to final location: {:?}", e);
+ return Err(ApiError::InternalError(Some("Failed to store blob".into())));
+ }
+
+ if let Err(e) = state
.repos
.blob
.insert_blob(
@@ -160,24 +166,9 @@ pub async fn upload_blob(
)
.await
{
- Ok(_) => {}
- Err(e) => {
- let _ = state.blob_store.delete(&temp_key).await;
- error!("Failed to insert blob record: {:?}", e);
- return Err(ApiError::InternalError(None));
- }
- };
-
- if let Err(e) = state.blob_store.copy(&temp_key, &storage_key).await {
let _ = state.blob_store.delete(&temp_key).await;
- if let Err(db_err) = state.repos.blob.delete_blob_by_cid(&cid_link).await {
- error!(
- "Failed to clean up orphaned blob record after copy failure: {:?}",
- db_err
- );
- }
- error!("Failed to copy blob to final location: {:?}", e);
- return Err(ApiError::InternalError(Some("Failed to store blob".into())));
+ error!("Failed to insert blob record: {:?}", e);
+ return Err(ApiError::InternalError(None));
}
let _ = state.blob_store.delete(&temp_key).await;
diff --git a/crates/tranquil-db/src/postgres/blob.rs b/crates/tranquil-db/src/postgres/blob.rs
index 6e69a83..f0a1f48 100644
--- a/crates/tranquil-db/src/postgres/blob.rs
+++ b/crates/tranquil-db/src/postgres/blob.rs
@@ -33,7 +33,7 @@ impl BlobRepository for PostgresBlobRepository {
let result = sqlx::query_scalar!(
r#"INSERT INTO blobs (cid, mime_type, size_bytes, created_by_user, storage_key)
VALUES ($1, $2, $3, $4, $5)
- ON CONFLICT (cid) DO NOTHING RETURNING cid"#,
+ ON CONFLICT (cid, created_by_user) DO NOTHING RETURNING cid"#,
cid.as_str(),
mime_type,
size_bytes,
@@ -49,7 +49,7 @@ impl BlobRepository for PostgresBlobRepository {
async fn get_blob_metadata(&self, cid: &CidLink) -> Result