Deduplicate artifact bytes and deliver files by authenticated hash

This commit is contained in:
2026-10-06 14:35:13 -04:00
parent 18283c63a7
commit 62df14b180
45 changed files with 510 additions and 139 deletions
@@ -0,0 +1,17 @@
import { error } from '@sveltejs/kit';
import { authenticateAgent } from '$lib/server/hosts/http.js';
import { db } from '$lib/server/db/index.js';
export function GET({ request, params }: { request: Request; params: { sha256: string } }) {
const host = authenticateAgent(request);
if (!/^[a-f0-9]{64}$/.test(params.sha256)) error(404, 'File not found.');
const row = db().prepare(`SELECT b.content,b.size FROM file_blobs b WHERE b.sha256=? AND EXISTS (
SELECT 1 FROM file_blob_references r JOIN ec_host_operations o ON o.id=r.owner_id
WHERE r.sha256=b.sha256 AND r.owner_type='operation' AND o.host_id=?)`).get(params.sha256, host.id) as
{ content: Buffer; size: number } | undefined;
if (!row) error(404, 'File not found.');
return new Response(new Uint8Array(row.content), { headers: {
'Content-Type': 'application/octet-stream', 'Content-Length': String(row.size),
'Cache-Control': 'private, no-store', ETag: `"${params.sha256}"`
} });
}
@@ -1,3 +1,4 @@
import { blobContent } from '$lib/server/db/file-blobs.js';
import { db } from '$lib/server/db/index.js';
/** Current files can be reviewed before the first revision is archived. */
@@ -5,12 +6,12 @@ export async function GET({ params }: { params: { id: string; revision: string;
const values = [params.id, params.revision, params.scriptId].map(Number);
if (values.some(value => !Number.isSafeInteger(value) || value < 1)) return new Response('Invalid file', { status: 400 });
const [id, revision, scriptId] = values;
const file = db().prepare('SELECT content FROM beta_revision_files WHERE beta_id = ? AND revision = ? AND script_id = ?')
const file = db().prepare(`SELECT ${blobContent('content_hash')} AS content FROM beta_revision_files WHERE beta_id = ? AND revision = ? AND script_id = ?`)
.get(id, revision, scriptId) as { content: Buffer } | undefined
?? (revision === 1 ? db().prepare(`SELECT v.content FROM beta_scripts bs JOIN script_versions v ON v.id = bs.script_version_id
?? (revision === 1 ? db().prepare(`SELECT ${blobContent('v.content_hash')} AS content FROM beta_scripts bs JOIN script_versions v ON v.id = bs.script_version_id
WHERE bs.beta_id = ? AND bs.script_id = ? AND NOT EXISTS (SELECT 1 FROM beta_revisions WHERE beta_id = ?)`)
.get(id, scriptId, id) as { content: Buffer } | undefined : undefined);
if (!file) return new Response('File not found', { status: 404 });
if (!file?.content) return new Response('File not found', { status: 404 });
return new Response(new Uint8Array(file.content), { headers: { 'Content-Type': 'application/octet-stream',
'Content-Disposition': 'attachment', 'Cache-Control': 'no-store' } });
}
+3 -2
View File
@@ -1,3 +1,4 @@
import { blobSize } from '$lib/server/db/file-blobs.js';
import { json, error } from '@sveltejs/kit';
import { db } from '$lib/server/db/index.js';
@@ -16,8 +17,8 @@ export async function GET({ params }: { params: { id: string } }) {
const files = db()
.prepare(
`SELECT id, server, verb, rel_path, sha256_before, sha256_after, snapshot_pending,
LENGTH(content_before) AS size_before,
LENGTH(content_after) AS size_after,
${blobSize('content_before_hash')} AS size_before,
${blobSize('content_after_hash')} AS size_after,
COALESCE((SELECT state FROM staged_file_changes WHERE deployment_file_id = deployment_files.id), 'applied') AS apply_state
FROM deployment_files
WHERE deployment_id = ?
@@ -1,3 +1,4 @@
import { blobContent } from '$lib/server/db/file-blobs.js';
import { json, error } from '@sveltejs/kit';
import { db } from '$lib/server/db/index.js';
@@ -10,7 +11,7 @@ export async function GET({ params }: { params: { id: string; fileId: string } }
}
const row = db()
.prepare(
`SELECT verb, rel_path, sha256_before, sha256_after, content_before, content_after, snapshot_pending
`SELECT verb, rel_path, sha256_before, sha256_after, ${blobContent('content_before_hash')} AS content_before, ${blobContent('content_after_hash')} AS content_after, snapshot_pending
FROM deployment_files
WHERE deployment_id = ? AND id = ?`
)
+3 -2
View File
@@ -1,3 +1,4 @@
import { blobSize } from '$lib/server/db/file-blobs.js';
import { json, error } from '@sveltejs/kit';
import { db } from '$lib/server/db/index.js';
import { getDeployment } from '$lib/server/provisioning/index.js';
@@ -19,8 +20,8 @@ export async function GET({ params, url }: { params: { id: string }; url?: URL }
const files = db()
.prepare(
`SELECT id, server, verb, rel_path, sha256_before, sha256_after,
LENGTH(content_before) AS size_before,
LENGTH(content_after) AS size_after
${blobSize('content_before_hash')} AS size_before,
${blobSize('content_after_hash')} AS size_after
FROM deployment_files
WHERE deployment_id = ?
ORDER BY server, rel_path`
@@ -1,3 +1,4 @@
import { blobContent } from '$lib/server/db/file-blobs.js';
import { json, error } from '@sveltejs/kit';
import { db } from '$lib/server/db/index.js';
@@ -7,7 +8,7 @@ import { db } from '$lib/server/db/index.js';
export async function GET({ params }: { params: { id: string; fileId: string } }) {
const row = db()
.prepare(
`SELECT verb, rel_path, sha256_before, sha256_after, content_before, content_after
`SELECT verb, rel_path, sha256_before, sha256_after, ${blobContent('content_before_hash')} AS content_before, ${blobContent('content_after_hash')} AS content_after
FROM deployment_files
WHERE deployment_id = ? AND id = ?`
)