57 lines
2.0 KiB
Python
57 lines
2.0 KiB
Python
from celery import shared_task
|
|
|
|
from .models import Certificate, CertificateStatus
|
|
from .renderer import RenderError, compute_pdf_hash, render_certificate_pdf
|
|
from .services import get_pdf_storage_path
|
|
|
|
|
|
@shared_task(
|
|
name="certificates.render_certificate",
|
|
bind=True,
|
|
autoretry_for=(Exception,),
|
|
retry_kwargs={"max_retries": 3, "countdown": 60},
|
|
)
|
|
def render_certificate_task(self, certificate_id: str):
|
|
"""
|
|
Async task: render a certificate PDF, compute its hash, and persist the result.
|
|
Retried up to 3 times on failure with 60s delay.
|
|
"""
|
|
from django.utils.timezone import now
|
|
|
|
try:
|
|
cert = Certificate.objects.select_related("user", "course").get(pk=certificate_id)
|
|
except Certificate.DoesNotExist:
|
|
return {"error": f"Certificate {certificate_id} not found"}
|
|
|
|
cert.status = CertificateStatus.RENDERING
|
|
cert.render_attempts += 1
|
|
cert.save(update_fields=["status", "render_attempts", "updated_at"])
|
|
|
|
context = {
|
|
"recipient_name": getattr(cert.user, "display_name", "") or cert.user.email,
|
|
"course_title": cert.course.title,
|
|
"issued_date": now().strftime("%B %d, %Y"),
|
|
"serial_number": cert.serial_number,
|
|
"verification_url": cert.verification_url,
|
|
}
|
|
|
|
output_path = get_pdf_storage_path(cert)
|
|
|
|
try:
|
|
render_certificate_pdf(context, output_path)
|
|
pdf_hash = compute_pdf_hash(output_path)
|
|
except RenderError as exc:
|
|
cert.status = CertificateStatus.FAILED
|
|
cert.render_error = str(exc)
|
|
cert.save(update_fields=["status", "render_error", "updated_at"])
|
|
raise # triggers Celery retry
|
|
|
|
cert.status = CertificateStatus.COMPLETED
|
|
cert.pdf_path = output_path
|
|
cert.pdf_hash = pdf_hash
|
|
cert.issued_at = now()
|
|
cert.render_error = ""
|
|
cert.save(update_fields=["status", "pdf_path", "pdf_hash", "issued_at", "render_error", "updated_at"])
|
|
|
|
return {"certificate_id": certificate_id, "serial": cert.serial_number, "hash": pdf_hash}
|