use date-fns for dates

This commit is contained in:
Georges-Antoine Assi
2025-10-16 09:07:26 -04:00
parent 949466e642
commit cdd856f865
2 changed files with 44 additions and 11 deletions

View File

@@ -6,6 +6,7 @@ from pathlib import Path
from typing import Any, Dict, List
from PIL import Image, UnidentifiedImageError
from rq import get_current_job
from config import (
ENABLE_SCHEDULED_CONVERT_IMAGES_TO_WEBP,
@@ -104,6 +105,24 @@ class ConvertImagesToWebPTask(PeriodicTask):
self.converter = ImageConverter()
self._reset_counters()
def _update_job_meta(self, total_files: int) -> None:
"""Update the current RQ job's meta data with conversion stats information"""
conversion_stats = {
"processed": self.processed_count,
"errors": self.error_count,
"total": total_files,
"errorList": self.errors[:10],
}
try:
current_job = get_current_job()
if current_job:
current_job.meta.update({"conversion_stats": conversion_stats})
current_job.save_meta()
except Exception as e:
# Silently fail if we can't update meta (e.g., not running in RQ context)
log.debug(f"Could not update job meta: {e}")
def _reset_counters(self) -> None:
"""Reset processing counters."""
self.processed_count = 0
@@ -178,6 +197,7 @@ class ConvertImagesToWebPTask(PeriodicTask):
total_files = len(image_files)
if total_files == 0:
self._update_job_meta(total_files)
log.info("No convertible images found")
return self._create_result_dict(total_files)
@@ -189,6 +209,7 @@ class ConvertImagesToWebPTask(PeriodicTask):
# Process images
for i, image_file in enumerate(image_files, 1):
self._process_single_image(image_file)
self._update_job_meta(total_files)
# Log progress periodically
if i % 50 == 0 or i == total_files:

View File

@@ -1,4 +1,9 @@
<script setup lang="ts">
import {
formatDistanceToNow,
intervalToDuration,
formatDuration,
} from "date-fns";
import { computed } from "vue";
import { formatTimestamp } from "@/utils";
import { TaskStatusItem, type TaskStatusResponse } from "@/utils/tasks";
@@ -16,16 +21,18 @@ const taskDuration = computed(() => {
if (!props.task.started_at) return null;
if (!props.task.ended_at && props.task.status === "failed") return null;
const startTime = new Date(props.task.started_at);
const endTime = props.task.ended_at
? new Date(props.task.ended_at)
: new Date();
const duration = endTime.getTime() - startTime.getTime();
const duration = intervalToDuration({
start: new Date(props.task.started_at),
end: props.task.ended_at ? new Date(props.task.ended_at) : new Date(),
});
return formatDuration(duration);
});
if (duration < 1000) return "< 1s";
if (duration < 60000) return `${Math.round(duration / 1000)}s`;
if (duration < 3600000) return `${Math.round(duration / 60000)}m`;
return `${Math.round(duration / 3600000)}h`;
const taskDistanceFromNow = computed(() => {
return formatDistanceToNow(
new Date(props.task.started_at || props.task.queued_at),
{ addSuffix: true },
);
});
</script>
@@ -74,8 +81,13 @@ const taskDuration = computed(() => {
/>
{{ task.status }}
</v-chip>
<v-chip size="small" variant="tonal" class="text-caption">
{{ formatTimestamp(task.started_at || task.queued_at) }}
<v-chip
size="small"
variant="tonal"
class="text-caption"
:title="formatTimestamp(task.started_at || task.queued_at)"
>
{{ taskDistanceFromNow }}
</v-chip>
</div>
</div>