diff --git a/app/controllers/api/v1/widget/conversations_controller.rb b/app/controllers/api/v1/widget/conversations_controller.rb index 69b85797c..1d1ba8a7e 100644 --- a/app/controllers/api/v1/widget/conversations_controller.rb +++ b/app/controllers/api/v1/widget/conversations_controller.rb @@ -28,7 +28,7 @@ class Api::V1::Widget::ConversationsController < Api::V1::Widget::BaseController conversation.contact_last_seen_at = DateTime.now.utc conversation.save! - ::Conversations::MarkMessagesAsReadJob.perform_later(conversation.id, conversation.contact_last_seen_at) + ::Conversations::UpdateMessageStatusJob.perform_later(conversation.id, conversation.contact_last_seen_at) head :ok end diff --git a/app/controllers/public/api/v1/inboxes/conversations_controller.rb b/app/controllers/public/api/v1/inboxes/conversations_controller.rb index 3242942f4..671863bdc 100644 --- a/app/controllers/public/api/v1/inboxes/conversations_controller.rb +++ b/app/controllers/public/api/v1/inboxes/conversations_controller.rb @@ -23,7 +23,7 @@ class Public::Api::V1::Inboxes::ConversationsController < Public::Api::V1::Inbox def update_last_seen @conversation.contact_last_seen_at = DateTime.now.utc @conversation.save! - ::Conversations::MarkMessagesAsReadJob.perform_later(@conversation.id, @conversation.contact_last_seen_at) + ::Conversations::UpdateMessageStatusJob.perform_later(@conversation.id, @conversation.contact_last_seen_at) head :ok end diff --git a/app/jobs/conversations/mark_messages_as_read_job.rb b/app/jobs/conversations/mark_messages_as_read_job.rb deleted file mode 100644 index 212b8569f..000000000 --- a/app/jobs/conversations/mark_messages_as_read_job.rb +++ /dev/null @@ -1,16 +0,0 @@ -class Conversations::MarkMessagesAsReadJob < ApplicationJob - queue_as :low - - def perform(conversation_id, timestamp) - conversation = Conversation.find_by(id: conversation_id) - - return unless conversation - - # Mark every message created before the user's viewing time as read. - conversation.messages.where(status: %w[sent delivered]) - .where.not(message_type: 'incoming') - .where('messages.created_at <= ?', timestamp).find_each do |message| - message.update!(status: 'read') - end - end -end diff --git a/app/jobs/conversations/update_message_status_job.rb b/app/jobs/conversations/update_message_status_job.rb new file mode 100644 index 000000000..1e6333b41 --- /dev/null +++ b/app/jobs/conversations/update_message_status_job.rb @@ -0,0 +1,21 @@ +class Conversations::UpdateMessageStatusJob < ApplicationJob + queue_as :low + + # This job only support marking messages as read or delivered, update this array if we want to support more statuses + VALID_STATUSES = %w[read delivered].freeze + + def perform(conversation_id, timestamp, status = :read) + return unless VALID_STATUSES.include?(status.to_s) + + conversation = Conversation.find_by(id: conversation_id) + + return unless conversation + + # Mark every message created before the user's viewing time read or delivered + conversation.messages.where(status: %w[sent delivered]) + .where.not(message_type: 'incoming') + .where('messages.created_at <= ?', timestamp).find_each do |message| + message.update!(status: status) + end + end +end diff --git a/app/services/instagram/read_status_service.rb b/app/services/instagram/read_status_service.rb index 41ef7246a..c96d369ea 100644 --- a/app/services/instagram/read_status_service.rb +++ b/app/services/instagram/read_status_service.rb @@ -4,7 +4,7 @@ class Instagram::ReadStatusService def perform return if instagram_channel.blank? - ::Conversations::MarkMessagesAsReadJob.perform_later(message.conversation.id, message.created_at) if message.present? + ::Conversations::UpdateMessageStatusJob.perform_later(message.conversation.id, message.created_at) if message.present? end def instagram_id diff --git a/spec/controllers/api/v1/widget/conversations_controller_spec.rb b/spec/controllers/api/v1/widget/conversations_controller_spec.rb index 15bfb6855..c3fd7ff26 100644 --- a/spec/controllers/api/v1/widget/conversations_controller_spec.rb +++ b/spec/controllers/api/v1/widget/conversations_controller_spec.rb @@ -173,7 +173,7 @@ RSpec.describe '/api/v1/widget/conversations/toggle_typing', type: :request do allow(Rails.configuration.dispatcher).to receive(:dispatch) expect(conversation.contact_last_seen_at).to be_nil - expect(Conversations::MarkMessagesAsReadJob).to receive(:perform_later).with(conversation.id, current_time) + expect(Conversations::UpdateMessageStatusJob).to receive(:perform_later).with(conversation.id, current_time) post '/api/v1/widget/conversations/update_last_seen', headers: { 'X-Auth-Token' => token }, diff --git a/spec/controllers/public/api/v1/inbox/conversations_controller_spec.rb b/spec/controllers/public/api/v1/inbox/conversations_controller_spec.rb index 7e1779b4a..d54f26272 100644 --- a/spec/controllers/public/api/v1/inbox/conversations_controller_spec.rb +++ b/spec/controllers/public/api/v1/inbox/conversations_controller_spec.rb @@ -83,7 +83,7 @@ RSpec.describe 'Public Inbox Contact Conversations API', type: :request do current_time = DateTime.now.utc allow(DateTime).to receive(:now).and_return(current_time) contact_last_seen_at = conversation.contact_last_seen_at - expect(Conversations::MarkMessagesAsReadJob).to receive(:perform_later).with(conversation.id, current_time) + expect(Conversations::UpdateMessageStatusJob).to receive(:perform_later).with(conversation.id, current_time) post update_last_seen_path expect(response).to have_http_status(:success) diff --git a/spec/jobs/conversations/mark_messages_as_read_job_spec.rb b/spec/jobs/conversations/update_message_status_job_spec.rb similarity index 81% rename from spec/jobs/conversations/mark_messages_as_read_job_spec.rb rename to spec/jobs/conversations/update_message_status_job_spec.rb index e4eff0f0a..0cdfb867d 100644 --- a/spec/jobs/conversations/mark_messages_as_read_job_spec.rb +++ b/spec/jobs/conversations/update_message_status_job_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -RSpec.describe Conversations::MarkMessagesAsReadJob do +RSpec.describe Conversations::UpdateMessageStatusJob do subject(:job) { described_class.perform_later(account) } let!(:account) { create(:account) } @@ -21,6 +21,13 @@ RSpec.describe Conversations::MarkMessagesAsReadJob do end.to change(message, :status).from('sent').to('read') end + it 'marks all sent messages in a conversation as delivered if specified' do + expect do + described_class.perform_now(conversation.id, conversation.contact_last_seen_at, :delivered) + message.reload + end.to change(message, :status).from('sent').to('delivered') + end + it 'marks all delivered messages in a conversation as read' do message.update!(status: 'delivered') expect do @@ -63,5 +70,11 @@ RSpec.describe Conversations::MarkMessagesAsReadJob do described_class.perform_now(1212, conversation.contact_last_seen_at) end.not_to change(message.reload, :status) end + + it 'does not run the job if the status is failed' do + expect do + described_class.perform_now(conversation.id, conversation.contact_last_seen_at, :failed) + end.not_to change(message.reload, :status) + end end end diff --git a/spec/services/instagram/read_status_service_spec.rb b/spec/services/instagram/read_status_service_spec.rb index 669fcd4f9..535c481c7 100644 --- a/spec/services/instagram/read_status_service_spec.rb +++ b/spec/services/instagram/read_status_service_spec.rb @@ -18,10 +18,10 @@ describe Instagram::ReadStatusService do let(:message) { conversation.messages.last } before do - allow(Conversations::MarkMessagesAsReadJob).to receive(:perform_later) + allow(Conversations::UpdateMessageStatusJob).to receive(:perform_later) end - it 'enqueues the MarkMessagesAsReadJob with correct parameters if the message is found' do + it 'enqueues the UpdateMessageStatusJob with correct parameters if the message is found' do params = { recipient: { id: 'chatwoot-app-user-id-1' @@ -31,10 +31,10 @@ describe Instagram::ReadStatusService do } } described_class.new(params: params).perform - expect(Conversations::MarkMessagesAsReadJob).to have_received(:perform_later).with(conversation.id, message.created_at) + expect(Conversations::UpdateMessageStatusJob).to have_received(:perform_later).with(conversation.id, message.created_at) end - it 'does not enqueue the MarkMessagesAsReadJob if the message is not found' do + it 'does not enqueue the UpdateMessageStatusJob if the message is not found' do params = { recipient: { id: 'chatwoot-app-user-id-1' @@ -44,7 +44,7 @@ describe Instagram::ReadStatusService do } } described_class.new(params: params).perform - expect(Conversations::MarkMessagesAsReadJob).not_to have_received(:perform_later) + expect(Conversations::UpdateMessageStatusJob).not_to have_received(:perform_later) end end end