diff --git a/app/jobs/channels/whatsapp/templates_sync_job.rb b/app/jobs/channels/whatsapp/templates_sync_job.rb new file mode 100644 index 000000000..a9ea4616c --- /dev/null +++ b/app/jobs/channels/whatsapp/templates_sync_job.rb @@ -0,0 +1,7 @@ +class Channels::Whatsapp::TemplatesSyncJob < ApplicationJob + queue_as :low + + def perform(whatsapp_channel) + whatsapp_channel.sync_templates + end +end diff --git a/app/jobs/channels/whatsapp/templates_sync_scheduler_job.rb b/app/jobs/channels/whatsapp/templates_sync_scheduler_job.rb new file mode 100644 index 000000000..1b11c32c4 --- /dev/null +++ b/app/jobs/channels/whatsapp/templates_sync_scheduler_job.rb @@ -0,0 +1,12 @@ +class Channels::Whatsapp::TemplatesSyncSchedulerJob < ApplicationJob + queue_as :low + + def perform + Channel::Whatsapp.where('message_templates_last_updated <= ? OR message_templates_last_updated IS NULL', + 15.minutes.ago).find_in_batches do |channels_batch| + channels_batch.each do |channel| + Channels::Whatsapp::TemplatesSyncJob.perform_later(channel) + end + end + end +end diff --git a/app/jobs/trigger_scheduled_items_job.rb b/app/jobs/trigger_scheduled_items_job.rb index 5d1b89727..a3a502ec0 100644 --- a/app/jobs/trigger_scheduled_items_job.rb +++ b/app/jobs/trigger_scheduled_items_job.rb @@ -12,5 +12,8 @@ class TriggerScheduledItemsJob < ApplicationJob # Job to auto-resolve conversations Account::ConversationsResolutionSchedulerJob.perform_later + + # Job to sync whatsapp templates + Channels::Whatsapp::TemplatesSyncSchedulerJob.perform_later end end diff --git a/app/models/channel/whatsapp.rb b/app/models/channel/whatsapp.rb index a97dcc930..1f7a14c39 100644 --- a/app/models/channel/whatsapp.rb +++ b/app/models/channel/whatsapp.rb @@ -25,6 +25,7 @@ class Channel::Whatsapp < ApplicationRecord validates :phone_number, presence: true, uniqueness: true before_save :validate_provider_config + after_create :sync_templates def name 'Whatsapp' @@ -62,10 +63,6 @@ class Channel::Whatsapp < ApplicationRecord end def sync_templates - # to prevent too many api calls - last_updated = message_templates_last_updated || 1.day.ago - return if Time.current < (last_updated + 12.hours) - response = HTTParty.get("#{api_base_path}/configs/templates", headers: api_headers) update(message_templates: response['waba_templates'], message_templates_last_updated: Time.now.utc) if response.success? end diff --git a/app/services/whatsapp/send_on_whatsapp_service.rb b/app/services/whatsapp/send_on_whatsapp_service.rb index be81c332b..efba78f7e 100644 --- a/app/services/whatsapp/send_on_whatsapp_service.rb +++ b/app/services/whatsapp/send_on_whatsapp_service.rb @@ -15,7 +15,6 @@ class Whatsapp::SendOnWhatsappService < Base::SendOnChannelService end def send_template_message - channel.sync_templates name, namespace, lang_code, processed_parameters = processable_channel_message_template return if name.blank? diff --git a/spec/factories/channel/channel_whatsapp.rb b/spec/factories/channel/channel_whatsapp.rb index 0c60cc78f..3db99b47a 100644 --- a/spec/factories/channel/channel_whatsapp.rb +++ b/spec/factories/channel/channel_whatsapp.rb @@ -34,6 +34,15 @@ FactoryBot.define do end message_templates_last_updated { Time.now.utc } + transient do + sync_templates { true } + end + + before(:create) do |channel_whatsapp, options| + # since factory already has the required message templates, we just need to bypass it getting updated + channel_whatsapp.define_singleton_method(:sync_templates) { return } unless options.sync_templates + end + after(:create) do |channel_whatsapp| create(:inbox, channel: channel_whatsapp, account: channel_whatsapp.account) end diff --git a/spec/jobs/channels/whatsapp/templates_sync_job_spec.rb b/spec/jobs/channels/whatsapp/templates_sync_job_spec.rb new file mode 100644 index 000000000..335e4d6f7 --- /dev/null +++ b/spec/jobs/channels/whatsapp/templates_sync_job_spec.rb @@ -0,0 +1,20 @@ +require 'rails_helper' + +RSpec.describe Channels::Whatsapp::TemplatesSyncJob, type: :job do + let(:channel_whatsapp) { create(:channel_whatsapp, sync_templates: false) } + + it 'enqueues the job' do + stub_request(:post, 'https://waba.360dialog.io/v1/configs/webhook') + expect { described_class.perform_later(channel_whatsapp) }.to have_enqueued_job(described_class) + .on_queue('low') + end + + context 'when called' do + it 'calls sync_templates' do + whatsapp_channel = double + allow(whatsapp_channel).to receive(:sync_templates).and_return(true) + expect(whatsapp_channel).to receive(:sync_templates) + described_class.perform_now(whatsapp_channel) + end + end +end diff --git a/spec/jobs/channels/whatsapp/templates_sync_scheduler_job_spec.rb b/spec/jobs/channels/whatsapp/templates_sync_scheduler_job_spec.rb new file mode 100644 index 000000000..6d345584d --- /dev/null +++ b/spec/jobs/channels/whatsapp/templates_sync_scheduler_job_spec.rb @@ -0,0 +1,27 @@ +require 'rails_helper' + +RSpec.describe Channels::Whatsapp::TemplatesSyncSchedulerJob, type: :job do + it 'enqueues the job' do + expect { described_class.perform_later }.to have_enqueued_job(described_class) + .on_queue('low') + end + + context 'when called' do + it 'schedules templates_sync_jobs for channels where templates need to be updated' do + stub_request(:post, 'https://waba.360dialog.io/v1/configs/webhook') + non_synced = create(:channel_whatsapp, sync_templates: false, message_templates_last_updated: nil) + synced_recently = create(:channel_whatsapp, sync_templates: false, message_templates_last_updated: Time.zone.now) + synced_old = create(:channel_whatsapp, sync_templates: false, message_templates_last_updated: 16.minutes.ago) + described_class.perform_now + expect(Channels::Whatsapp::TemplatesSyncJob).not_to( + have_been_enqueued.with(synced_recently).on_queue('low') + ) + expect(Channels::Whatsapp::TemplatesSyncJob).to( + have_been_enqueued.with(synced_old).on_queue('low') + ) + expect(Channels::Whatsapp::TemplatesSyncJob).to( + have_been_enqueued.with(non_synced).on_queue('low') + ) + end + end +end diff --git a/spec/jobs/send_reply_job_spec.rb b/spec/jobs/send_reply_job_spec.rb index 03b249368..304653b41 100644 --- a/spec/jobs/send_reply_job_spec.rb +++ b/spec/jobs/send_reply_job_spec.rb @@ -66,9 +66,9 @@ RSpec.describe SendReplyJob, type: :job do described_class.perform_now(message.id) end - it 'calls ::Whatsapp:SendOnWhatsappService when its line message' do + it 'calls ::Whatsapp:SendOnWhatsappService when its whatsapp message' do stub_request(:post, 'https://waba.360dialog.io/v1/configs/webhook') - whatsapp_channel = create(:channel_whatsapp) + whatsapp_channel = create(:channel_whatsapp, sync_templates: false) message = create(:message, conversation: create(:conversation, inbox: whatsapp_channel.inbox)) allow(::Whatsapp::SendOnWhatsappService).to receive(:new).with(message: message).and_return(process_service) expect(::Whatsapp::SendOnWhatsappService).to receive(:new).with(message: message) diff --git a/spec/jobs/trigger_scheduled_items_job_spec.rb b/spec/jobs/trigger_scheduled_items_job_spec.rb index f94371e8b..e7b5fe597 100644 --- a/spec/jobs/trigger_scheduled_items_job_spec.rb +++ b/spec/jobs/trigger_scheduled_items_job_spec.rb @@ -30,5 +30,10 @@ RSpec.describe TriggerScheduledItemsJob, type: :job do expect(Account::ConversationsResolutionSchedulerJob).to receive(:perform_later).once described_class.perform_now end + + it 'triggers Channels::Whatsapp::TemplatesSyncSchedulerJob' do + expect(Channels::Whatsapp::TemplatesSyncSchedulerJob).to receive(:perform_later).once + described_class.perform_now + end end end diff --git a/spec/services/whatsapp/incoming_message_service_spec.rb b/spec/services/whatsapp/incoming_message_service_spec.rb index 0144dd169..efe9949f5 100644 --- a/spec/services/whatsapp/incoming_message_service_spec.rb +++ b/spec/services/whatsapp/incoming_message_service_spec.rb @@ -6,7 +6,7 @@ describe Whatsapp::IncomingMessageService do stub_request(:post, 'https://waba.360dialog.io/v1/configs/webhook') end - let!(:whatsapp_channel) { create(:channel_whatsapp) } + let!(:whatsapp_channel) { create(:channel_whatsapp, sync_templates: false) } context 'when valid text message params' do it 'creates appropriate conversations, message and contacts' do diff --git a/spec/services/whatsapp/send_on_whatsapp_service_spec.rb b/spec/services/whatsapp/send_on_whatsapp_service_spec.rb index b08f25931..1dc405abd 100644 --- a/spec/services/whatsapp/send_on_whatsapp_service_spec.rb +++ b/spec/services/whatsapp/send_on_whatsapp_service_spec.rb @@ -15,7 +15,7 @@ describe Whatsapp::SendOnWhatsappService do context 'when a valid message' do let(:whatsapp_request) { double } - let!(:whatsapp_channel) { create(:channel_whatsapp) } + let!(:whatsapp_channel) { create(:channel_whatsapp, sync_templates: false) } let!(:contact_inbox) { create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: '123456789') } let!(:conversation) { create(:conversation, contact_inbox: contact_inbox, inbox: whatsapp_channel.inbox) }