| 30 |
30 |
|
Ok(blob)
|
| 31 |
31 |
|
}
|
| 32 |
32 |
|
|
|
33 |
+ |
/// Sum the bytes a user currently stores for an app. `sync_blobs` is the
|
|
34 |
+ |
/// authoritative record, so this is the same number the quota gate enforces
|
|
35 |
+ |
/// against; there is no counter to drift. Generic over the executor so the
|
|
36 |
+ |
/// status route can ask the pool and `confirm_internal_blob` can ask inside
|
|
37 |
+ |
/// its own locked transaction.
|
|
38 |
+ |
async fn sum_blob_bytes<'e, E>(executor: E, app_id: SyncAppId, user_id: UserId) -> Result<i64>
|
|
39 |
+ |
where
|
|
40 |
+ |
E: sqlx::PgExecutor<'e>,
|
|
41 |
+ |
{
|
|
42 |
+ |
let used: i64 = sqlx::query_scalar(
|
|
43 |
+ |
"SELECT COALESCE(SUM(size_bytes), 0)::BIGINT FROM sync_blobs
|
|
44 |
+ |
WHERE app_id = $1 AND user_id = $2",
|
|
45 |
+ |
)
|
|
46 |
+ |
.bind(app_id)
|
|
47 |
+ |
.bind(user_id)
|
|
48 |
+ |
.fetch_one(executor)
|
|
49 |
+ |
.await?;
|
|
50 |
+ |
Ok(used)
|
|
51 |
+ |
}
|
|
52 |
+ |
|
|
53 |
+ |
/// Bytes a user currently stores for an app, for the subscription-status
|
|
54 |
+ |
/// route. Summed live rather than cached: the same query already runs on every
|
|
55 |
+ |
/// blob confirm, and `sync_blobs` is indexed on `(app_id, user_id)`.
|
|
56 |
+ |
#[tracing::instrument(skip_all)]
|
|
57 |
+ |
pub async fn storage_used_bytes(pool: &PgPool, app_id: SyncAppId, user_id: UserId) -> Result<i64> {
|
|
58 |
+ |
sum_blob_bytes(pool, app_id, user_id).await
|
|
59 |
+ |
}
|
|
60 |
+ |
|
| 33 |
61 |
|
/// Result of an atomic blob-confirm. Every variant is terminal for one confirm
|
| 34 |
62 |
|
/// call; the route handler maps it to a 204 or a 402 with the right reason.
|
| 35 |
63 |
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
| 130 |
158 |
|
return Ok(BlobConfirm::AlreadyStored);
|
| 131 |
159 |
|
}
|
| 132 |
160 |
|
|
| 133 |
|
- |
let used: i64 = sqlx::query_scalar(
|
| 134 |
|
- |
"SELECT COALESCE(SUM(size_bytes), 0)::BIGINT FROM sync_blobs
|
| 135 |
|
- |
WHERE app_id = $1 AND user_id = $2",
|
| 136 |
|
- |
)
|
| 137 |
|
- |
.bind(app_id)
|
| 138 |
|
- |
.bind(user_id)
|
| 139 |
|
- |
.fetch_one(&mut *tx)
|
| 140 |
|
- |
.await?;
|
|
161 |
+ |
let used = sum_blob_bytes(&mut *tx, app_id, user_id).await?;
|
| 141 |
162 |
|
let limit = limit.unwrap_or(0);
|
| 142 |
163 |
|
if used.saturating_add(size_bytes) > limit {
|
| 143 |
164 |
|
return Ok(BlobConfirm::QuotaExceeded {
|