feat: add auto-increment id, size/duration tracking, and soft cleanup to conversion_jobs

Rename the old CHAR(36) id to uuid (still used for public URLs and file
naming) and add a real auto-increment id as the primary key. Track
input/output file size and conversion duration per job. Cleanup no
longer deletes rows; it marks cleaned_at and skips already-cleaned
expired jobs on later runs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-30 22:06:32 +02:00
co-authored by Claude Sonnet 5
parent 24f7ab2625
commit ff5a257a0e
10 changed files with 208 additions and 117 deletions
+29 -18
View File
@@ -2,6 +2,7 @@ function toCamelJob(row) {
if (!row) return null;
return {
id: row.id,
uuid: row.uuid,
status: row.status,
family: row.family,
sourceFormat: row.source_format,
@@ -11,38 +12,44 @@ function toCamelJob(row) {
outputPath: row.output_path,
inputMimeType: row.input_mime_type,
outputMimeType: row.output_mime_type,
inputSizeBytes: row.input_size_bytes,
outputSizeBytes: row.output_size_bytes,
conversionDurationSeconds: row.conversion_duration_seconds,
errorMessage: row.error_message,
createdAt: row.created_at,
updatedAt: row.updated_at,
expiresAt: row.expires_at,
cleanedAt: row.cleaned_at,
};
}
export async function createJob(pool, job) {
await pool.query(
`INSERT INTO conversion_jobs
(id, status, family, source_format, target_format, original_filename, input_path, input_mime_type, expires_at)
VALUES (?, 'pending', ?, ?, ?, ?, ?, ?, ?)`,
(uuid, status, family, source_format, target_format, original_filename, input_path, input_mime_type, input_size_bytes, expires_at)
VALUES (?, 'pending', ?, ?, ?, ?, ?, ?, ?, ?)`,
[
job.id,
job.uuid,
job.family,
job.sourceFormat,
job.targetFormat,
job.originalFilename,
job.inputPath,
job.inputMimeType,
job.inputSizeBytes,
job.expiresAt,
]
);
}
export async function getJobById(pool, id) {
export async function getJobByUuid(pool, uuid) {
const rows = await pool.query(
`SELECT id, status, family, source_format, target_format, original_filename,
`SELECT id, uuid, status, family, source_format, target_format, original_filename,
input_path, output_path, input_mime_type, output_mime_type,
error_message, created_at, updated_at, expires_at
FROM conversion_jobs WHERE id = ?`,
[id]
input_size_bytes, output_size_bytes, conversion_duration_seconds,
error_message, created_at, updated_at, expires_at, cleaned_at
FROM conversion_jobs WHERE uuid = ?`,
[uuid]
);
return toCamelJob(rows[0]);
}
@@ -56,10 +63,12 @@ export async function markProcessing(pool, id) {
await pool.query("UPDATE conversion_jobs SET status = 'processing' WHERE id = ?", [id]);
}
export async function markDone(pool, id, { outputPath, outputMimeType }) {
export async function markDone(pool, id, { outputPath, outputMimeType, outputSizeBytes, conversionDurationSeconds }) {
await pool.query(
"UPDATE conversion_jobs SET status = 'done', output_path = ?, output_mime_type = ? WHERE id = ?",
[outputPath, outputMimeType, id]
`UPDATE conversion_jobs
SET status = 'done', output_path = ?, output_mime_type = ?, output_size_bytes = ?, conversion_duration_seconds = ?
WHERE id = ?`,
[outputPath, outputMimeType, outputSizeBytes, conversionDurationSeconds, id]
);
}
@@ -72,9 +81,10 @@ export async function markFailed(pool, id, { errorMessage, errorLog }) {
export async function findPendingJobs(pool, limit) {
const rows = await pool.query(
`SELECT id, status, family, source_format, target_format, original_filename,
`SELECT id, uuid, status, family, source_format, target_format, original_filename,
input_path, output_path, input_mime_type, output_mime_type,
error_message, created_at, updated_at, expires_at
input_size_bytes, output_size_bytes, conversion_duration_seconds,
error_message, created_at, updated_at, expires_at, cleaned_at
FROM conversion_jobs WHERE status = 'pending' ORDER BY created_at ASC LIMIT ?`,
[limit]
);
@@ -83,14 +93,15 @@ export async function findPendingJobs(pool, limit) {
export async function findExpiredJobs(pool) {
const rows = await pool.query(
`SELECT id, status, family, source_format, target_format, original_filename,
`SELECT id, uuid, status, family, source_format, target_format, original_filename,
input_path, output_path, input_mime_type, output_mime_type,
error_message, created_at, updated_at, expires_at
FROM conversion_jobs WHERE expires_at < NOW()`
input_size_bytes, output_size_bytes, conversion_duration_seconds,
error_message, created_at, updated_at, expires_at, cleaned_at
FROM conversion_jobs WHERE expires_at < NOW() AND cleaned_at IS NULL`
);
return rows.map(toCamelJob);
}
export async function deleteJob(pool, id) {
await pool.query('DELETE FROM conversion_jobs WHERE id = ?', [id]);
export async function markCleaned(pool, id) {
await pool.query('UPDATE conversion_jobs SET cleaned_at = NOW() WHERE id = ?', [id]);
}