From 314d88a882baff3ea3f3ffdd6a7a69114b1f0fe2 Mon Sep 17 00:00:00 2001 From: moltenhub-bot Date: Mon, 4 May 2026 10:51:40 -0700 Subject: [PATCH] refactor: reduce codebase and centralize classes --- ...send_form_completed_webhook_request_job.rb | 47 +++--------- .../send_form_declined_webhook_request_job.rb | 41 ++-------- .../send_form_started_webhook_request_job.rb | 41 ++-------- .../send_form_viewed_webhook_request_job.rb | 41 ++-------- ...submission_archived_webhook_request_job.rb | 38 ++-------- ...ubmission_completed_webhook_request_job.rb | 38 ++-------- ..._submission_created_webhook_request_job.rb | 38 ++-------- ..._submission_expired_webhook_request_job.rb | 38 ++-------- ...d_template_archived_webhook_request_job.rb | 38 ++-------- ...nd_template_created_webhook_request_job.rb | 38 ++-------- ...nd_template_updated_webhook_request_job.rb | 38 ++-------- app/jobs/send_test_webhook_request_job.rb | 16 ++-- lib/webhook_request_job.rb | 74 +++++++++++++++++++ lib/webhook_urls.rb | 29 ++++---- 14 files changed, 160 insertions(+), 395 deletions(-) create mode 100644 lib/webhook_request_job.rb diff --git a/app/jobs/send_form_completed_webhook_request_job.rb b/app/jobs/send_form_completed_webhook_request_job.rb index e025bb4c..840820fc 100644 --- a/app/jobs/send_form_completed_webhook_request_job.rb +++ b/app/jobs/send_form_completed_webhook_request_job.rb @@ -1,42 +1,13 @@ # frozen_string_literal: true class SendFormCompletedWebhookRequestJob - include Sidekiq::Job - - sidekiq_options queue: :webhooks - - MAX_ATTEMPTS = 12 - - def perform(params = {}) - submitter = Submitter.find_by(id: params['submitter_id']) - - return unless submitter - - webhook_url = WebhookUrl.find_by(id: params['webhook_url_id']) - - return unless webhook_url - - attempt = params['attempt'].to_i - - return if webhook_url.url.blank? || webhook_url.events.exclude?('form.completed') - - Submissions::EnsureResultGenerated.call(submitter) - - ActiveStorage::Current.url_options = Docuseal.default_url_options - - resp = SendWebhookRequest.call(webhook_url, event_type: 'form.completed', - event_uuid: params['event_uuid'], - record: submitter, - attempt:, - data: Submitters::SerializeForWebhook.call(submitter)) - - if (resp.nil? || resp.status.to_i >= 400) && attempt <= MAX_ATTEMPTS && - (!Docuseal.multitenant? || submitter.account.account_configs.exists?(key: :plan)) - SendFormCompletedWebhookRequestJob.perform_in((2**attempt).minutes, { - **params, - 'attempt' => attempt + 1, - 'last_status' => resp&.status.to_i - }) - end - end + include WebhookRequestJob + + webhook_request event_type: 'form.completed', + record_class: Submitter, + record_id_param: 'submitter_id', + data: Submitters::SerializeForWebhook, + max_attempts: 12, + ensure_result_generated: true, + default_url_options: true end diff --git a/app/jobs/send_form_declined_webhook_request_job.rb b/app/jobs/send_form_declined_webhook_request_job.rb index 32d63bde..dfb67319 100644 --- a/app/jobs/send_form_declined_webhook_request_job.rb +++ b/app/jobs/send_form_declined_webhook_request_job.rb @@ -1,40 +1,11 @@ # frozen_string_literal: true class SendFormDeclinedWebhookRequestJob - include Sidekiq::Job + include WebhookRequestJob - sidekiq_options queue: :webhooks - - MAX_ATTEMPTS = 10 - - def perform(params = {}) - submitter = Submitter.find_by(id: params['submitter_id']) - - return unless submitter - - webhook_url = WebhookUrl.find_by(id: params['webhook_url_id']) - - return unless webhook_url - - attempt = params['attempt'].to_i - - return if webhook_url.url.blank? || webhook_url.events.exclude?('form.declined') - - ActiveStorage::Current.url_options = Docuseal.default_url_options - - resp = SendWebhookRequest.call(webhook_url, event_type: 'form.declined', - event_uuid: params['event_uuid'], - record: submitter, - attempt:, - data: Submitters::SerializeForWebhook.call(submitter)) - - if (resp.nil? || resp.status.to_i >= 400) && attempt <= MAX_ATTEMPTS && - (!Docuseal.multitenant? || submitter.account.account_configs.exists?(key: :plan)) - SendFormDeclinedWebhookRequestJob.perform_in((2**attempt).minutes, { - **params, - 'attempt' => attempt + 1, - 'last_status' => resp&.status.to_i - }) - end - end + webhook_request event_type: 'form.declined', + record_class: Submitter, + record_id_param: 'submitter_id', + data: Submitters::SerializeForWebhook, + default_url_options: true end diff --git a/app/jobs/send_form_started_webhook_request_job.rb b/app/jobs/send_form_started_webhook_request_job.rb index cc278d2a..013bbb41 100644 --- a/app/jobs/send_form_started_webhook_request_job.rb +++ b/app/jobs/send_form_started_webhook_request_job.rb @@ -1,40 +1,11 @@ # frozen_string_literal: true class SendFormStartedWebhookRequestJob - include Sidekiq::Job + include WebhookRequestJob - sidekiq_options queue: :webhooks - - MAX_ATTEMPTS = 10 - - def perform(params = {}) - submitter = Submitter.find_by(id: params['submitter_id']) - - return unless submitter - - webhook_url = WebhookUrl.find_by(id: params['webhook_url_id']) - - return unless webhook_url - - attempt = params['attempt'].to_i - - return if webhook_url.url.blank? || webhook_url.events.exclude?('form.started') - - ActiveStorage::Current.url_options = Docuseal.default_url_options - - resp = SendWebhookRequest.call(webhook_url, event_type: 'form.started', - event_uuid: params['event_uuid'], - record: submitter, - attempt:, - data: Submitters::SerializeForWebhook.call(submitter)) - - if (resp.nil? || resp.status.to_i >= 400) && attempt <= MAX_ATTEMPTS && - (!Docuseal.multitenant? || submitter.account.account_configs.exists?(key: :plan)) - SendFormStartedWebhookRequestJob.perform_in((2**attempt).minutes, { - **params, - 'attempt' => attempt + 1, - 'last_status' => resp&.status.to_i - }) - end - end + webhook_request event_type: 'form.started', + record_class: Submitter, + record_id_param: 'submitter_id', + data: Submitters::SerializeForWebhook, + default_url_options: true end diff --git a/app/jobs/send_form_viewed_webhook_request_job.rb b/app/jobs/send_form_viewed_webhook_request_job.rb index 8f6f0d6d..b8cd3da1 100644 --- a/app/jobs/send_form_viewed_webhook_request_job.rb +++ b/app/jobs/send_form_viewed_webhook_request_job.rb @@ -1,40 +1,11 @@ # frozen_string_literal: true class SendFormViewedWebhookRequestJob - include Sidekiq::Job + include WebhookRequestJob - sidekiq_options queue: :webhooks - - MAX_ATTEMPTS = 10 - - def perform(params = {}) - submitter = Submitter.find_by(id: params['submitter_id']) - - return unless submitter - - webhook_url = WebhookUrl.find_by(id: params['webhook_url_id']) - - return unless webhook_url - - attempt = params['attempt'].to_i - - return if webhook_url.url.blank? || webhook_url.events.exclude?('form.viewed') - - ActiveStorage::Current.url_options = Docuseal.default_url_options - - resp = SendWebhookRequest.call(webhook_url, event_type: 'form.viewed', - event_uuid: params['event_uuid'], - record: submitter, - attempt:, - data: Submitters::SerializeForWebhook.call(submitter)) - - if (resp.nil? || resp.status.to_i >= 400) && attempt <= MAX_ATTEMPTS && - (!Docuseal.multitenant? || submitter.account.account_configs.exists?(key: :plan)) - SendFormViewedWebhookRequestJob.perform_in((2**attempt).minutes, { - **params, - 'attempt' => attempt + 1, - 'last_status' => resp&.status.to_i - }) - end - end + webhook_request event_type: 'form.viewed', + record_class: Submitter, + record_id_param: 'submitter_id', + data: Submitters::SerializeForWebhook, + default_url_options: true end diff --git a/app/jobs/send_submission_archived_webhook_request_job.rb b/app/jobs/send_submission_archived_webhook_request_job.rb index 77ba6d57..18453291 100644 --- a/app/jobs/send_submission_archived_webhook_request_job.rb +++ b/app/jobs/send_submission_archived_webhook_request_job.rb @@ -1,38 +1,10 @@ # frozen_string_literal: true class SendSubmissionArchivedWebhookRequestJob - include Sidekiq::Job + include WebhookRequestJob - sidekiq_options queue: :webhooks - - MAX_ATTEMPTS = 10 - - def perform(params = {}) - submission = Submission.find_by(id: params['submission_id']) - - return unless submission - - webhook_url = WebhookUrl.find_by(id: params['webhook_url_id']) - - return unless webhook_url - - attempt = params['attempt'].to_i - - return if webhook_url.url.blank? || webhook_url.events.exclude?('submission.archived') - - resp = SendWebhookRequest.call(webhook_url, event_type: 'submission.archived', - event_uuid: params['event_uuid'], - record: submission, - attempt:, - data: submission.as_json(only: %i[id archived_at])) - - if (resp.nil? || resp.status.to_i >= 400) && attempt <= MAX_ATTEMPTS && - (!Docuseal.multitenant? || submission.account.account_configs.exists?(key: :plan)) - SendSubmissionArchivedWebhookRequestJob.perform_in((2**attempt).minutes, { - **params, - 'attempt' => attempt + 1, - 'last_status' => resp&.status.to_i - }) - end - end + webhook_request event_type: 'submission.archived', + record_class: Submission, + record_id_param: 'submission_id', + data: ->(submission) { submission.as_json(only: %i[id archived_at]) } end diff --git a/app/jobs/send_submission_completed_webhook_request_job.rb b/app/jobs/send_submission_completed_webhook_request_job.rb index 3832eb35..636e49b3 100644 --- a/app/jobs/send_submission_completed_webhook_request_job.rb +++ b/app/jobs/send_submission_completed_webhook_request_job.rb @@ -1,38 +1,10 @@ # frozen_string_literal: true class SendSubmissionCompletedWebhookRequestJob - include Sidekiq::Job + include WebhookRequestJob - sidekiq_options queue: :webhooks - - MAX_ATTEMPTS = 10 - - def perform(params = {}) - submission = Submission.find_by(id: params['submission_id']) - - return unless submission - - webhook_url = WebhookUrl.find_by(id: params['webhook_url_id']) - - return unless webhook_url - - attempt = params['attempt'].to_i - - return if webhook_url.url.blank? || webhook_url.events.exclude?('submission.completed') - - resp = SendWebhookRequest.call(webhook_url, event_type: 'submission.completed', - event_uuid: params['event_uuid'], - record: submission, - attempt:, - data: Submissions::SerializeForApi.call(submission)) - - if (resp.nil? || resp.status.to_i >= 400) && attempt <= MAX_ATTEMPTS && - (!Docuseal.multitenant? || submission.account.account_configs.exists?(key: :plan)) - SendSubmissionCompletedWebhookRequestJob.perform_in((2**attempt).minutes, { - **params, - 'attempt' => attempt + 1, - 'last_status' => resp&.status.to_i - }) - end - end + webhook_request event_type: 'submission.completed', + record_class: Submission, + record_id_param: 'submission_id', + data: Submissions::SerializeForApi end diff --git a/app/jobs/send_submission_created_webhook_request_job.rb b/app/jobs/send_submission_created_webhook_request_job.rb index c9fb1ff6..69773f5c 100644 --- a/app/jobs/send_submission_created_webhook_request_job.rb +++ b/app/jobs/send_submission_created_webhook_request_job.rb @@ -1,38 +1,10 @@ # frozen_string_literal: true class SendSubmissionCreatedWebhookRequestJob - include Sidekiq::Job + include WebhookRequestJob - sidekiq_options queue: :webhooks - - MAX_ATTEMPTS = 10 - - def perform(params = {}) - submission = Submission.find_by(id: params['submission_id']) - - return unless submission - - webhook_url = WebhookUrl.find_by(id: params['webhook_url_id']) - - return unless webhook_url - - attempt = params['attempt'].to_i - - return if webhook_url.url.blank? || webhook_url.events.exclude?('submission.created') - - resp = SendWebhookRequest.call(webhook_url, event_type: 'submission.created', - event_uuid: params['event_uuid'], - record: submission, - attempt:, - data: Submissions::SerializeForApi.call(submission)) - - if (resp.nil? || resp.status.to_i >= 400) && attempt <= MAX_ATTEMPTS && - (!Docuseal.multitenant? || submission.account.account_configs.exists?(key: :plan)) - SendSubmissionCreatedWebhookRequestJob.perform_in((2**attempt).minutes, { - **params, - 'attempt' => attempt + 1, - 'last_status' => resp&.status.to_i - }) - end - end + webhook_request event_type: 'submission.created', + record_class: Submission, + record_id_param: 'submission_id', + data: Submissions::SerializeForApi end diff --git a/app/jobs/send_submission_expired_webhook_request_job.rb b/app/jobs/send_submission_expired_webhook_request_job.rb index d89b4f3a..6446f701 100644 --- a/app/jobs/send_submission_expired_webhook_request_job.rb +++ b/app/jobs/send_submission_expired_webhook_request_job.rb @@ -1,38 +1,10 @@ # frozen_string_literal: true class SendSubmissionExpiredWebhookRequestJob - include Sidekiq::Job + include WebhookRequestJob - sidekiq_options queue: :webhooks - - MAX_ATTEMPTS = 10 - - def perform(params = {}) - submission = Submission.find_by(id: params['submission_id']) - - return unless submission - - webhook_url = WebhookUrl.find_by(id: params['webhook_url_id']) - - return unless webhook_url - - attempt = params['attempt'].to_i - - return if webhook_url.url.blank? || webhook_url.events.exclude?('submission.expired') - - resp = SendWebhookRequest.call(webhook_url, event_type: 'submission.expired', - event_uuid: params['event_uuid'], - record: submission, - attempt:, - data: Submissions::SerializeForApi.call(submission)) - - if (resp.nil? || resp.status.to_i >= 400) && attempt <= MAX_ATTEMPTS && - (!Docuseal.multitenant? || submission.account.account_configs.exists?(key: :plan)) - SendSubmissionExpiredWebhookRequestJob.perform_in((2**attempt).minutes, { - **params, - 'attempt' => attempt + 1, - 'last_status' => resp&.status.to_i - }) - end - end + webhook_request event_type: 'submission.expired', + record_class: Submission, + record_id_param: 'submission_id', + data: Submissions::SerializeForApi end diff --git a/app/jobs/send_template_archived_webhook_request_job.rb b/app/jobs/send_template_archived_webhook_request_job.rb index 1b1c7c92..916564d4 100644 --- a/app/jobs/send_template_archived_webhook_request_job.rb +++ b/app/jobs/send_template_archived_webhook_request_job.rb @@ -1,38 +1,10 @@ # frozen_string_literal: true class SendTemplateArchivedWebhookRequestJob - include Sidekiq::Job + include WebhookRequestJob - sidekiq_options queue: :webhooks - - MAX_ATTEMPTS = 10 - - def perform(params = {}) - template = Template.find_by(id: params['template_id']) - - return unless template - - webhook_url = WebhookUrl.find_by(id: params['webhook_url_id']) - - return unless webhook_url - - attempt = params['attempt'].to_i - - return if webhook_url.url.blank? || webhook_url.events.exclude?('template.archived') - - resp = SendWebhookRequest.call(webhook_url, event_type: 'template.archived', - event_uuid: params['event_uuid'], - record: template, - attempt:, - data: template.as_json(only: %i[id archived_at])) - - if (resp.nil? || resp.status.to_i >= 400) && attempt <= MAX_ATTEMPTS && - (!Docuseal.multitenant? || template.account.account_configs.exists?(key: :plan)) - SendTemplateArchivedWebhookRequestJob.perform_in((2**attempt).minutes, { - **params, - 'attempt' => attempt + 1, - 'last_status' => resp&.status.to_i - }) - end - end + webhook_request event_type: 'template.archived', + record_class: Template, + record_id_param: 'template_id', + data: ->(template) { template.as_json(only: %i[id archived_at]) } end diff --git a/app/jobs/send_template_created_webhook_request_job.rb b/app/jobs/send_template_created_webhook_request_job.rb index cb0af29f..3c248dc4 100644 --- a/app/jobs/send_template_created_webhook_request_job.rb +++ b/app/jobs/send_template_created_webhook_request_job.rb @@ -1,38 +1,10 @@ # frozen_string_literal: true class SendTemplateCreatedWebhookRequestJob - include Sidekiq::Job + include WebhookRequestJob - sidekiq_options queue: :webhooks - - MAX_ATTEMPTS = 10 - - def perform(params = {}) - template = Template.find_by(id: params['template_id']) - - return unless template - - webhook_url = WebhookUrl.find_by(id: params['webhook_url_id']) - - return unless webhook_url - - attempt = params['attempt'].to_i - - return if webhook_url.url.blank? || webhook_url.events.exclude?('template.created') - - resp = SendWebhookRequest.call(webhook_url, event_type: 'template.created', - event_uuid: params['event_uuid'], - record: template, - attempt:, - data: Templates::SerializeForApi.call(template)) - - if (resp.nil? || resp.status.to_i >= 400) && attempt <= MAX_ATTEMPTS && - (!Docuseal.multitenant? || template.account.account_configs.exists?(key: :plan)) - SendTemplateCreatedWebhookRequestJob.perform_in((2**attempt).minutes, { - **params, - 'attempt' => attempt + 1, - 'last_status' => resp&.status.to_i - }) - end - end + webhook_request event_type: 'template.created', + record_class: Template, + record_id_param: 'template_id', + data: Templates::SerializeForApi end diff --git a/app/jobs/send_template_updated_webhook_request_job.rb b/app/jobs/send_template_updated_webhook_request_job.rb index 46a67dcc..692970e0 100644 --- a/app/jobs/send_template_updated_webhook_request_job.rb +++ b/app/jobs/send_template_updated_webhook_request_job.rb @@ -1,38 +1,10 @@ # frozen_string_literal: true class SendTemplateUpdatedWebhookRequestJob - include Sidekiq::Job + include WebhookRequestJob - sidekiq_options queue: :webhooks - - MAX_ATTEMPTS = 10 - - def perform(params = {}) - template = Template.find_by(id: params['template_id']) - - return unless template - - webhook_url = WebhookUrl.find_by(id: params['webhook_url_id']) - - return unless webhook_url - - attempt = params['attempt'].to_i - - return if webhook_url.url.blank? || webhook_url.events.exclude?('template.updated') - - resp = SendWebhookRequest.call(webhook_url, event_type: 'template.updated', - event_uuid: params['event_uuid'], - record: template, - attempt:, - data: Templates::SerializeForApi.call(template)) - - if (resp.nil? || resp.status.to_i >= 400) && attempt <= MAX_ATTEMPTS && - (!Docuseal.multitenant? || template.account.account_configs.exists?(key: :plan)) - SendTemplateUpdatedWebhookRequestJob.perform_in((2**attempt).minutes, { - **params, - 'attempt' => attempt + 1, - 'last_status' => resp&.status.to_i - }) - end - end + webhook_request event_type: 'template.updated', + record_class: Template, + record_id_param: 'template_id', + data: Templates::SerializeForApi end diff --git a/app/jobs/send_test_webhook_request_job.rb b/app/jobs/send_test_webhook_request_job.rb index 0116cdaf..e56c9270 100644 --- a/app/jobs/send_test_webhook_request_job.rb +++ b/app/jobs/send_test_webhook_request_job.rb @@ -5,11 +5,6 @@ class SendTestWebhookRequestJob sidekiq_options retry: 0 - USER_AGENT = 'DocuSeal.com Webhook' - - HttpsError = Class.new(StandardError) - LocalhostError = Class.new(StandardError) - def perform(params = {}) submitter = Submitter.find_by(id: params['submitter_id']) @@ -26,8 +21,13 @@ class SendTestWebhookRequestJob Addressable::URI.parse(webhook_url.url).normalize end - raise HttpsError, 'Only HTTPS is allowed.' if uri.scheme != 'https' || [443, nil].exclude?(uri.port) - raise LocalhostError, "Can't send to localhost." if uri.host.in?(SendWebhookRequest::LOCALHOSTS) + if uri.scheme != 'https' || [443, nil].exclude?(uri.port) + raise SendWebhookRequest::HttpsError, 'Only HTTPS is allowed.' + end + + if uri.host.in?(SendWebhookRequest::LOCALHOSTS) + raise SendWebhookRequest::LocalhostError, "Can't send to localhost." + end end Faraday.post(webhook_url.url, @@ -37,7 +37,7 @@ class SendTestWebhookRequestJob data: Submitters::SerializeForWebhook.call(submitter) }.to_json, 'Content-Type' => 'application/json', - 'User-Agent' => USER_AGENT, + 'User-Agent' => SendWebhookRequest::USER_AGENT, **webhook_url.secret.to_h) end end diff --git a/lib/webhook_request_job.rb b/lib/webhook_request_job.rb new file mode 100644 index 00000000..4d5c4be5 --- /dev/null +++ b/lib/webhook_request_job.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +module WebhookRequestJob + def self.included(base) + base.include Sidekiq::Job + base.extend ClassMethods + base.sidekiq_options queue: :webhooks + end + + module ClassMethods + attr_reader :webhook_request_config + + def webhook_request(event_type:, record_class:, record_id_param:, data:, max_attempts: 10, + ensure_result_generated: false, default_url_options: false) + @webhook_request_config = { + event_type:, + record_class:, + record_id_param:, + data:, + max_attempts:, + ensure_result_generated:, + default_url_options: + }.freeze + end + end + + def perform(params = {}) + config = self.class.webhook_request_config + record = config[:record_class].find_by(id: params[config[:record_id_param]]) + + return unless record + + webhook_url = WebhookUrl.find_by(id: params['webhook_url_id']) + + return unless webhook_url + + attempt = params['attempt'].to_i + event_type = config[:event_type] + + return if webhook_url.url.blank? || webhook_url.events.exclude?(event_type) + + prepare_record(record, config) + + response = SendWebhookRequest.call(webhook_url, event_type:, + event_uuid: params['event_uuid'], + record:, + attempt:, + data: config[:data].call(record)) + + enqueue_retry(params, record, response, attempt, config) + end + + private + + def prepare_record(record, config) + Submissions::EnsureResultGenerated.call(record) if config[:ensure_result_generated] + ActiveStorage::Current.url_options = Docuseal.default_url_options if config[:default_url_options] + end + + def enqueue_retry(params, record, response, attempt, config) + return unless retry_webhook_request?(record, response, attempt, config) + + self.class.perform_in((2**attempt).minutes, { + **params, + 'attempt' => attempt + 1, + 'last_status' => response&.status.to_i + }) + end + + def retry_webhook_request?(record, response, attempt, config) + (response.nil? || response.status.to_i >= 400) && attempt <= config[:max_attempts] && + (!Docuseal.multitenant? || record.account.account_configs.exists?(key: :plan)) + end +end diff --git a/lib/webhook_urls.rb b/lib/webhook_urls.rb index 242c274c..d4d02cf5 100644 --- a/lib/webhook_urls.rb +++ b/lib/webhook_urls.rb @@ -1,19 +1,22 @@ # frozen_string_literal: true module WebhookUrls - EVENT_TYPE_TO_JOB_CLASS = { - 'form.started' => SendFormStartedWebhookRequestJob, - 'form.completed' => SendFormCompletedWebhookRequestJob, - 'form.declined' => SendFormDeclinedWebhookRequestJob, - 'form.viewed' => SendFormViewedWebhookRequestJob, - 'submission.created' => SendSubmissionCreatedWebhookRequestJob, - 'submission.completed' => SendSubmissionCompletedWebhookRequestJob, - 'submission.expired' => SendSubmissionExpiredWebhookRequestJob, - 'submission.archived' => SendSubmissionArchivedWebhookRequestJob, - 'template.created' => SendTemplateCreatedWebhookRequestJob, - 'template.updated' => SendTemplateUpdatedWebhookRequestJob, - 'template.archived' => SendTemplateArchivedWebhookRequestJob - }.freeze + EVENT_JOB_CLASSES = [ + SendFormStartedWebhookRequestJob, + SendFormCompletedWebhookRequestJob, + SendFormDeclinedWebhookRequestJob, + SendFormViewedWebhookRequestJob, + SendSubmissionCreatedWebhookRequestJob, + SendSubmissionCompletedWebhookRequestJob, + SendSubmissionExpiredWebhookRequestJob, + SendSubmissionArchivedWebhookRequestJob, + SendTemplateCreatedWebhookRequestJob, + SendTemplateUpdatedWebhookRequestJob, + SendTemplateArchivedWebhookRequestJob + ].freeze + + EVENT_TYPE_TO_JOB_CLASS = + EVENT_JOB_CLASSES.index_by { |job_class| job_class.webhook_request_config.fetch(:event_type) }.freeze EVENT_TYPE_ID_KEYS = { 'form' => 'submitter_id',