From 3cefa9b767903046c35c777be2ea799d0c533b66 Mon Sep 17 00:00:00 2001 From: Sojan Jose Date: Wed, 27 Aug 2025 14:42:11 +0200 Subject: [PATCH] feat: add ops task to purge orphan conversations (#12279) ## Summary Add ops task to find and remove conversations missing contacts or inboxes. You can run this via ``` bundle exec rake chatwoot:ops:cleanup_orphan_conversations ``` fixes: https://linear.app/chatwoot/issue/CW-5439/conversations-missing-contacts --- .../ops/cleanup_orphan_conversations.rake | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 lib/tasks/ops/cleanup_orphan_conversations.rake diff --git a/lib/tasks/ops/cleanup_orphan_conversations.rake b/lib/tasks/ops/cleanup_orphan_conversations.rake new file mode 100644 index 000000000..f6574b396 --- /dev/null +++ b/lib/tasks/ops/cleanup_orphan_conversations.rake @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +# Run with: +# bundle exec rake chatwoot:ops:cleanup_orphan_conversations + +namespace :chatwoot do + namespace :ops do + desc 'Identify and delete conversations without a valid contact or inbox in a timeframe' + task cleanup_orphan_conversations: :environment do + print 'Enter Account ID: ' + account_id = $stdin.gets.to_i + account = Account.find(account_id) + + print 'Enter timeframe in days (default: 7): ' + days_input = $stdin.gets.strip + days = days_input.empty? ? 7 : days_input.to_i + + # Build a common base relation with identical joins for OR compatibility + base = account + .conversations + .where('conversations.created_at > ?', days.days.ago) + .left_outer_joins(:contact, :inbox) + + # Find conversations whose associated contact or inbox record is missing + conversations = base.where(contacts: { id: nil }).or(base.where(inboxes: { id: nil })) + + count = conversations.count + puts "Found #{count} conversations without a valid contact or inbox." + + if count.positive? + print 'Do you want to delete these conversations? (y/N): ' + confirm = $stdin.gets.strip.downcase + if %w[y yes].include?(confirm) + conversations.destroy_all + puts 'Conversations deleted.' + else + puts 'No conversations were deleted.' + end + end + end + end +end