Class: Assistant::EmailPluginRenderer

Inherits:
Object
  • Object
show all
Defined in:
app/services/assistant/email_plugin_renderer.rb

Overview

Drives the REAL Redactor 4 email plugin in a server-side headless Chromium to
produce an EmailTemplate's email-ready HTML (body_v4_email) from its
editor-semantic body_v4 — the only sanctioned way to render body_v4_email
(the plugin's getEmail() is client-side JS with no server port).

It mints a single-use Assistant::EmailRenderToken (scoped to the template id +
its current lock_version), opens the token-authenticated render harness
(Crm::EmailRenderHarnessController), waits for the editor to initialize, calls
window.emailRenderGetEmail() in-page, and POSTs the result back to the harness
which saves it under optimistic locking. The save is rejected if body_v4
changed since the token was minted, so a stale render never clobbers newer
source — the caller (EmailRenderJob) re-mints and retries.

Mirrors Transport::PlaywrightPortalConnection's launch/diagnostics/timeout
conventions.

Defined Under Namespace

Classes: Result

Constant Summary collapse

60_000
RENDER_TIMEOUT =

Editor-ready / getEmail poll timeout (ms).

45_000
POLL_INTERVAL =

Poll interval while waiting for the editor + a non-empty getEmail() (ms).

300

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ EmailPluginRenderer

Returns a new instance of EmailPluginRenderer.

Parameters:

  • options (Hash) (defaults to: {})

    renderer options

Options Hash (options):

  • :headless (Boolean) — default: true

    run Chromium headless (false to watch in dev)

  • :logger (Logger) — default: Rails.logger

    logger for diagnostics

  • :base_url (String) — default: CRM_URL

    origin the render harness is served from



41
42
43
44
45
# File 'app/services/assistant/email_plugin_renderer.rb', line 41

def initialize(options = {})
  @headless = options.fetch(:headless, true)
  @logger = options[:logger] || Rails.logger
  @base_url = options[:base_url] || CRM_URL
end

Instance Attribute Details

#loggerObject (readonly)

Returns the value of attribute logger.



35
36
37
# File 'app/services/assistant/email_plugin_renderer.rb', line 35

def logger
  @logger
end

Instance Method Details

#render!(email_template) ⇒ Result

Render + persist body_v4_email for the given template.

Parameters:

Returns:



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'app/services/assistant/email_plugin_renderer.rb', line 50

def render!(email_template)
  return Result.new(success: false, message: 'Template not Redactor-4-ready') unless email_template.redactor_4_ready?
  return Result.new(success: false, message: 'body_v4 is blank') if email_template.body_v4.blank?

  nonce = SecureRandom.uuid
  lock_version = email_template.lock_version
  token = Assistant::EmailRenderToken.encode(
    email_template_id: email_template.id, lock_version: lock_version, nonce: nonce
  )

  drive(email_template, token)
rescue Playwright::Error, Playwright::TimeoutError => e
  logger.error("[EmailPluginRenderer] #{e.class}: #{e.message}")
  Result.new(success: false, message: "Browser render failed: #{e.message}")
rescue StandardError => e
  logger.error("[EmailPluginRenderer] Fatal: #{e.class}: #{e.message}")
  Result.new(success: false, message: "Render failed: #{e.message}")
end