PERF: reuse renderer when rendering email templates

PERF: reuse renderer when rendering email templates

Previous to this fix we were leaking methods on the internal action view template class per render.

This caused email generation to be very low and a steady memory leak in the application in sidekiq when sending out emails

The behavior change is new to Rails 6 so this fix does not need to be backported into stable.

diff --git a/app/mailers/user_notifications.rb b/app/mailers/user_notifications.rb
index ee5a516..de8ac56 100644
--- a/app/mailers/user_notifications.rb
+++ b/app/mailers/user_notifications.rb
@@ -589,7 +589,7 @@ class UserNotifications < ActionMailer::Base
       end
 
       unless translation_override_exists
-        html = UserNotificationRenderer.with_view_paths(Rails.configuration.paths["app/views"]).render(
+        html = UserNotificationRenderer.instance.render(
           template: 'email/notification',
           format: :html,
           locals: { context_posts: context_posts,
diff --git a/app/services/user_notification_renderer.rb b/app/services/user_notification_renderer.rb
index 8ad7d20..edf1171 100644
--- a/app/services/user_notification_renderer.rb
+++ b/app/services/user_notification_renderer.rb
@@ -4,4 +4,10 @@ class UserNotificationRenderer < ActionView::Base
   include ApplicationHelper
   include UserNotificationsHelper
   include EmailHelper
+
+  def self.instance
+    @instance ||= UserNotificationRenderer.with_view_paths(
+      Rails.configuration.paths["app/views"]
+    )
+  end
 end
diff --git a/lib/email/message_builder.rb b/lib/email/message_builder.rb
index d1e83b0..654c4ae 100644
--- a/lib/email/message_builder.rb
+++ b/lib/email/message_builder.rb
@@ -94,9 +94,7 @@ module Email
         html_override.gsub!("%{respond_instructions}", "")
       end
 
-      html = UserNotificationRenderer.with_view_paths(
-        Rails.configuration.paths["app/views"]
-      ).render(
+      html = UserNotificationRenderer.instance.render(
         template: 'layouts/email_template',
         format: :html,
         locals: { html_body: html_override.html_safe }
diff --git a/lib/email/renderer.rb b/lib/email/renderer.rb
index 641fb20..2f9203b 100644
--- a/lib/email/renderer.rb
+++ b/lib/email/renderer.rb
@@ -18,9 +18,7 @@ module Email
       style = if @message.html_part
         Email::Styles.new(@message.html_part.body.to_s, @opts)
       else
-        unstyled = UserNotificationRenderer.with_view_paths(
-          Rails.configuration.paths["app/views"]
-        ).render(
+        unstyled = UserNotificationRenderer.instance.render(
           template: 'layouts/email_template',
           format: :html,
           locals: { html_body: PrettyText.cook(text).html_safe }

GitHub sha: 71ea4ad7

4 Likes