diff --git a/app/jobs/channels/whatsapp/baileys_connection_check_job.rb b/app/jobs/channels/whatsapp/baileys_connection_check_job.rb new file mode 100644 index 000000000..3260ac84d --- /dev/null +++ b/app/jobs/channels/whatsapp/baileys_connection_check_job.rb @@ -0,0 +1,7 @@ +class Channels::Whatsapp::BaileysConnectionCheckJob < ApplicationJob + queue_as :low + + def perform(whatsapp_channel) + whatsapp_channel.setup_channel_provider + end +end diff --git a/app/jobs/channels/whatsapp/baileys_connection_check_scheduler_job.rb b/app/jobs/channels/whatsapp/baileys_connection_check_scheduler_job.rb new file mode 100644 index 000000000..58ebdf83a --- /dev/null +++ b/app/jobs/channels/whatsapp/baileys_connection_check_scheduler_job.rb @@ -0,0 +1,11 @@ +class Channels::Whatsapp::BaileysConnectionCheckSchedulerJob < ApplicationJob + queue_as :low + + def perform + Channel::Whatsapp.where(provider: 'baileys') + .where("provider_connection->>'connection' = ?", 'open') + .find_each do |channel| + Channels::Whatsapp::BaileysConnectionCheckJob.perform_later(channel) + end + end +end diff --git a/app/jobs/trigger_scheduled_items_job.rb b/app/jobs/trigger_scheduled_items_job.rb index 15b0011c8..29a72d14f 100644 --- a/app/jobs/trigger_scheduled_items_job.rb +++ b/app/jobs/trigger_scheduled_items_job.rb @@ -20,6 +20,9 @@ class TriggerScheduledItemsJob < ApplicationJob # Job to sync whatsapp templates Channels::Whatsapp::TemplatesSyncSchedulerJob.perform_later + # Job to check WhatsApp connection status + Channels::Whatsapp::BaileysConnectionCheckSchedulerJob.perform_later + # Job to clear notifications which are older than 1 month Notification::RemoveOldNotificationJob.perform_later end diff --git a/app/models/channel/whatsapp.rb b/app/models/channel/whatsapp.rb index d01d3bed1..77fc7a3b4 100644 --- a/app/models/channel/whatsapp.rb +++ b/app/models/channel/whatsapp.rb @@ -15,7 +15,8 @@ # # Indexes # -# index_channel_whatsapp_on_phone_number (phone_number) UNIQUE +# index_channel_whatsapp_baileys_connection (provider_connection) WHERE ((provider)::text = 'baileys'::text) USING gin +# index_channel_whatsapp_on_phone_number (phone_number) UNIQUE # class Channel::Whatsapp < ApplicationRecord diff --git a/db/migrate/20250726142410_add_whatsapp_channel_provider_index.rb b/db/migrate/20250726142410_add_whatsapp_channel_provider_index.rb new file mode 100644 index 000000000..f06c9caef --- /dev/null +++ b/db/migrate/20250726142410_add_whatsapp_channel_provider_index.rb @@ -0,0 +1,10 @@ +class AddWhatsappChannelProviderIndex < ActiveRecord::Migration[7.1] + disable_ddl_transaction! + + def change + add_index :channel_whatsapp, :provider_connection, + using: :gin, + where: "provider = 'baileys'", + name: 'index_channel_whatsapp_baileys_connection' + end +end diff --git a/db/schema.rb b/db/schema.rb index 81cb4f522..187277e83 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2025_07_14_104358) do +ActiveRecord::Schema[7.1].define(version: 2025_07_26_142410) do # These extensions should be enabled to support this database enable_extension "pg_stat_statements" enable_extension "pg_trgm" @@ -505,6 +505,7 @@ ActiveRecord::Schema[7.1].define(version: 2025_07_14_104358) do t.datetime "message_templates_last_updated", precision: nil t.jsonb "provider_connection", default: {} t.index ["phone_number"], name: "index_channel_whatsapp_on_phone_number", unique: true + t.index ["provider_connection"], name: "index_channel_whatsapp_baileys_connection", where: "((provider)::text = 'baileys'::text)", using: :gin end create_table "contact_inboxes", force: :cascade do |t| diff --git a/spec/jobs/channels/whatsapp/baileys_connection_check_job_spec.rb b/spec/jobs/channels/whatsapp/baileys_connection_check_job_spec.rb new file mode 100644 index 000000000..1763f0a7a --- /dev/null +++ b/spec/jobs/channels/whatsapp/baileys_connection_check_job_spec.rb @@ -0,0 +1,20 @@ +require 'rails_helper' + +RSpec.describe Channels::Whatsapp::BaileysConnectionCheckJob do + let(:channel_whatsapp) { create(:channel_whatsapp, sync_templates: false, validate_provider_config: false) } + + it 'enqueues the job' do + expect { described_class.perform_later(channel_whatsapp) }.to have_enqueued_job(described_class) + .on_queue('low') + end + + context 'when called' do + it 'calls setup_channel_provider' do + allow(channel_whatsapp).to receive(:setup_channel_provider).and_return(true) + + described_class.perform_now(channel_whatsapp) + + expect(channel_whatsapp).to have_received(:setup_channel_provider) + end + end +end diff --git a/spec/jobs/channels/whatsapp/baileys_connection_check_scheduler_job_spec.rb b/spec/jobs/channels/whatsapp/baileys_connection_check_scheduler_job_spec.rb new file mode 100644 index 000000000..c514c579e --- /dev/null +++ b/spec/jobs/channels/whatsapp/baileys_connection_check_scheduler_job_spec.rb @@ -0,0 +1,37 @@ +require 'rails_helper' + +RSpec.describe Channels::Whatsapp::BaileysConnectionCheckSchedulerJob 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 BaileysConnectionCheckJob for each WhatsApp channel with baileys provider connection open' do + channel = create(:channel_whatsapp, provider: 'baileys', provider_connection: { 'connection' => 'open' }, sync_templates: false, + validate_provider_config: false) + + described_class.perform_now + + expect(Channels::Whatsapp::BaileysConnectionCheckJob).to have_been_enqueued.with(channel).on_queue('low') + end + + it 'does not schedule BaileysConnectionCheckJob for channels with different provider' do + create(:channel_whatsapp, provider: 'whatsapp_cloud', provider_connection: { 'connection' => 'open' }, sync_templates: false, + validate_provider_config: false) + + expect do + described_class.perform_now + end.not_to have_enqueued_job(Channels::Whatsapp::BaileysConnectionCheckJob) + end + + it 'does not schedule BaileysConnectionCheckJob for channels with closed connection' do + create(:channel_whatsapp, provider: 'baileys', provider_connection: { 'connection' => 'closed' }, sync_templates: false, + validate_provider_config: false) + + expect do + described_class.perform_now + end.not_to have_enqueued_job(Channels::Whatsapp::BaileysConnectionCheckJob) + end + end +end diff --git a/spec/jobs/trigger_scheduled_items_job_spec.rb b/spec/jobs/trigger_scheduled_items_job_spec.rb index 4409e7ee0..0adb5f3b9 100644 --- a/spec/jobs/trigger_scheduled_items_job_spec.rb +++ b/spec/jobs/trigger_scheduled_items_job_spec.rb @@ -30,6 +30,11 @@ RSpec.describe TriggerScheduledItemsJob do described_class.perform_now end + it 'triggers Channels::Whatsapp::BaileysConnectionCheckSchedulerJob' do + expect(Channels::Whatsapp::BaileysConnectionCheckSchedulerJob).to receive(:perform_later).once + described_class.perform_now + end + it 'triggers Notification::RemoveOldNotificationJob' do expect(Notification::RemoveOldNotificationJob).to receive(:perform_later).once described_class.perform_now