from flask import current_app from requests import ( post as requests_post, RequestException ) from botocore.exceptions import ClientError as BotoClientError from sqlalchemy.orm.exc import NoResultFound from app import notify_celery from app.aws import s3 from app.config import QueueNames from app.dao.notifications_dao import get_notification_by_id, update_notification_status_by_id from app.statsd_decorators import statsd @notify_celery.task(bind=True, name="create-letters-pdf", max_retries=15, default_retry_delay=300) @statsd(namespace="tasks") def create_letters_pdf(self, notification_id): try: notification = get_notification_by_id(notification_id) if not notification: raise NoResultFound() pdf_data = get_letters_pdf( notification.template, contact_block=notification.reply_to_text, org_id=notification.service.dvla_organisation.id, values=notification.personalisation ) current_app.logger.info("PDF Letter {} reference {} created at {}, {} bytes".format( notification.id, notification.reference, notification.created_at, len(pdf_data))) s3.upload_letters_pdf(reference=notification.reference, crown=True, filedata=pdf_data) except (RequestException, BotoClientError): try: current_app.logger.exception( "Letters PDF notification creation for id: {} failed".format(notification_id) ) self.retry(queue=QueueNames.RETRY) except self.MaxRetriesExceededError: current_app.logger.exception( "RETRY FAILED: task create_letters_pdf failed for notification {}".format(notification_id), ) update_notification_status_by_id(notification_id, 'technical-failure') def get_letters_pdf(template, contact_block, org_id, values): template_for_letter_print = { "subject": template.subject, "content": template.content } data = { 'letter_contact_block': contact_block, 'template': template_for_letter_print, 'values': values, 'dvla_org_id': org_id, } resp = requests_post( '{}/print.pdf'.format( current_app.config['TEMPLATE_PREVIEW_API_HOST'] ), json=data, headers={'Authorization': 'Token {}'.format(current_app.config['TEMPLATE_PREVIEW_API_KEY'])} ) resp.raise_for_status() return resp.content