Class: EmailTemplateGetEmailRenderHandler

Inherits:
ApplicationJob
  • Object
show all
Includes:
RailsEventStore::AsyncHandler
Defined in:
app/subscribers/email_template_get_email_render_handler.rb

Overview

Async handler for Events::EmailTemplateBodyV4Changed.

Drives the REAL Redactor 4 email plugin in a headless Playwright browser
(Assistant::EmailPluginRenderer) to produce the template's email-ready
body_v4_email via getEmail(), so a draft authored by the assistant becomes
send-ready automatically — no human opening the CRM editor.

Runs asynchronously (ApplicationJob + RailsEventStore::AsyncHandler) so the
triggering save/request is never blocked by the browser round-trip. Mirrors
ArticlePublishedHandler's shape.

Idempotent: re-queries by id and no-ops if the template no longer needs a
render (already finalized, body_v4 cleared, or not R4). Bounded re-run for the
stale-source race (body_v4 changed mid-render) so a perpetually-edited template
can't loop forever.

Constant Summary collapse

RETRY_LIMIT =

Bounded in-perform retries for the stale-source race (distinct from
ApplicationJob's process-level retry, which covers crashes/timeouts).

2

Instance Method Summary collapse

Instance Method Details

#perform(event) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'app/subscribers/email_template_get_email_render_handler.rb', line 27

def perform(event)
  template = EmailTemplate.find_by(id: event.data[:email_template_id])
  return unless template&.redactor_4_ready?
  return if template.body_v4.blank?
  return if template.body_v4_email.present? # already finalized

  last = nil
  (1..(RETRY_LIMIT + 1)).each do |attempt|
    last = Assistant::EmailPluginRenderer.new.render!(template.reload)
    break if last.success?
    # Re-run only for the stale-source race; other failures are terminal here.
    break unless last.message.to_s.include?('stale') && attempt <= RETRY_LIMIT
  end

  return if last&.success?

  Rails.logger.warn("[EmailTemplateGetEmailRenderHandler] ##{template.id} did not finalize: #{last&.message}")
rescue StandardError => e
  ErrorReporting.error(e)
  raise
end