Skip to content

Commit ed1904d

Browse files
committed
Update cleanup cron to remove blobs without owners if enabled
1 parent ba72dab commit ed1904d

File tree

5 files changed

+71
-1
lines changed

5 files changed

+71
-1
lines changed

.changeset/nasty-dragons-search.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"blossom-server-ts": minor
3+
---
4+
5+
Update cleanup cron to remove blobs without owners if enabled

.changeset/strange-bananas-exist.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"blossom-server-ts": patch
3+
---
4+
5+
Throw 404 when blob is not found on DELETE /<sha256>

.github/workflows/publish-next.yml

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Release next
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
8+
concurrency: ${{ github.workflow }}-${{ github.ref }}
9+
10+
jobs:
11+
release:
12+
name: Release next
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- name: Checkout Repo
17+
uses: actions/checkout@v4
18+
19+
- uses: pnpm/action-setup@v4
20+
21+
- name: Setup Node.js 20
22+
uses: actions/setup-node@v4
23+
with:
24+
node-version: 20
25+
cache: "pnpm"
26+
27+
- name: Install Dependencies
28+
run: pnpm install
29+
30+
- name: Build package
31+
run: pnpm build
32+
33+
- name: Publish next version
34+
run: |
35+
pnpm config set //registry.npmjs.org/:_authToken=$NPM_TOKEN && \
36+
pnpm changeset version --snapshot next && \
37+
pnpm changeset publish --tag next
38+
env:
39+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

src/api/delete.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ router.delete<CommonState>("/:hash", async (ctx, next) => {
1818
if (hasUsedToken(ctx.state.auth.id)) throw new Error("Auth already used");
1919

2020
// skip if blob dose not exist
21-
if (!blobDB.hasBlob(sha256)) return;
21+
if (!blobDB.hasBlob(sha256)) throw new HttpErrors.NotFound("Blob does not exist");
2222

2323
const pubkey = ctx.state.auth.pubkey;
2424

src/storage/index.ts

+21
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import logger from "../logger.js";
1010
import { getExpirationTime } from "../rules/index.js";
1111
import { forgetBlobAccessed, updateBlobAccess } from "../db/methods.js";
1212
import { readUpload, removeUpload, UploadDetails } from "./upload.js";
13+
import { mapParams } from "../admin-api/helpers.js";
1314

1415
async function createStorage() {
1516
if (config.storage.backend === "local") {
@@ -82,6 +83,7 @@ export async function pruneStorage() {
8283
const now = dayjs().unix();
8384
const checked = new Set<string>();
8485

86+
/** Remove all blobs that no longer fall under any rules */
8587
for (const rule of config.storage.rules) {
8688
const expiration = getExpirationTime(rule, now);
8789
let blobs: (BlobMetadata & { pubkey: string; accessed: number | null })[] = [];
@@ -137,6 +139,25 @@ export async function pruneStorage() {
137139
}
138140
if (n > 0) log("Checked", n, "blobs for rule #" + config.storage.rules.indexOf(rule));
139141
}
142+
143+
// remove blobs with no owners
144+
if (config.storage.removeWhenNoOwners) {
145+
const blobs = db
146+
.prepare<[], { sha256: string }>(
147+
`
148+
SELECT blobs.sha256
149+
FROM blobs
150+
LEFT JOIN owners ON owners.blob = sha256
151+
WHERE owners.blob is NULL
152+
`,
153+
)
154+
.all();
155+
156+
if (blobs.length > 0) {
157+
log(`Removing ${blobs.length} because they have no owners`);
158+
db.prepare<string[]>(`DELETE FROM blobs WHERE sha256 IN ${mapParams(blobs)}`).run(...blobs.map((b) => b.sha256));
159+
}
160+
}
140161
}
141162

142163
export default storage;

0 commit comments

Comments
 (0)