ebed1caeb4
195 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
58f5ae6157 | Fix Wuzapi webhook handling | ||
|
|
9a4c5058f3 | Merge branch 'main' into chore/merge-upstream-4.11.0 | ||
|
|
7b512bd00e
|
fix: V2 Assignment service enhancements (#13036)
## Linear Ticket: https://linear.app/chatwoot/issue/CW-6081/review-feedback ## Description Assignment V2 Service Enhancements - Enable Assignment V2 on plan upgrade - Fix UI issue with fair distribution policy display - Add advanced assignment feature flag and enhance Assignment V2 capabilities ## Type of change - [ ] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? This has been tested using the UI. ## Checklist: - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my code - [ ] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes auto-assignment execution paths, rate limiting defaults, and feature-flag gating (including premium plan behavior), which could affect which conversations get assigned and when. UI rewires inbox settings and policy flows, so regressions are possible around navigation/linking and feature visibility. > > **Overview** > **Adds a new premium `advanced_assignment` feature flag** and uses it to gate capacity/balanced assignment features in the UI (sidebar entry, settings routes, assignment-policy landing cards) and backend (Enterprise balanced selector + capacity filtering). `advanced_assignment` is marked premium, included in Business plan entitlements, and auto-synced in Enterprise accounts when `assignment_v2` is toggled. > > **Improves Assignment V2 policy UX** by adding an inbox-level “Conversation Assignment” section (behind `assignment_v2`) that can link/unlink an assignment policy, navigate to create/edit policy flows with `inboxId` query context, and show an inbox-link prompt after creating a policy. The policy form now defaults to enabled, disables the `balanced` option with a premium badge/message when unavailable, and inbox lists support click-to-navigate. > > **Tightens/adjusts auto-assignment behavior**: bulk assignment now requires `inbox.enable_auto_assignment?`, conversation ordering uses the attached `assignment_policy` priority, and rate limiting uses `assignment_policy` config with an infinite default limit while still tracking assignments. Tests and i18n strings are updated accordingly. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 23bc03bf75ee4376071e4d7fc7cd564c601d33d7. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Pranav <pranav@chatwoot.com> Co-authored-by: iamsivin <iamsivin@gmail.com> Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com> Co-authored-by: Shivam Mishra <scm.mymail@gmail.com> |
||
|
|
9eb3ee44a8 |
Revert "chore: Upgrade Rails to 7.2.2 and update Gemfile dependencies (#11037)"
This reverts commit
|
||
|
|
ef6ba8aabd
|
chore: Upgrade Rails to 7.2.2 and update Gemfile dependencies (#11037)
Upgrade rails to 7.2.2 so that we can proceed with the rails 8 upgrade afterwards # Changelog - `.circleci/config.yml` — align CI DB setup with GitHub Actions (`db:create` + `db:schema:load`) to avoid trigger-dependent prep steps. - `.rubocop.yml` — add `rubocop-rspec_rails` and disable new cops that don't match existing spec style. - `AGENTS.md` — document that specs should run without `.env` (rename temporarily when present). - `Gemfile` — upgrade to Rails 7.2, switch Azure storage gem, pin `commonmarker`, bump `sidekiq-cron`, add `rubocop-rspec_rails`, and relax some gem pins. - `Gemfile.lock` — dependency lockfile updates from the Rails 7.2 and gem changes. - `app/controllers/api/v1/accounts/integrations/linear_controller.rb` — stringify params before passing to the Linear service to keep key types stable. - `app/controllers/super_admin/instance_statuses_controller.rb` — use `MigrationContext` API for migration status in Rails 7.2. - `app/models/installation_config.rb` — add commentary on YAML serialization and future JSONB migration (no behavior change). - `app/models/integrations/hook.rb` — ensure hook type is set on create only and guard against missing app. - `app/models/user.rb` — update enum syntax for Rails 7.2 deprecation, serialize OTP backup codes with JSON, and use Ruby `alias`. - `app/services/crm/leadsquared/setup_service.rb` — stringify hook settings keys before merge to keep JSON shape consistent. - `app/services/macros/execution_service.rb` — remove macro-specific assignee activity workaround; rely on standard assignment handlers. - `config/application.rb` — load Rails 7.2 defaults. - `config/storage.yml` — update Azure Active Storage service name to `AzureBlob`. - `db/migrate/20230515051424_update_article_image_keys.rb` — use credentials `secret_key_base` with fallback to legacy secrets. - `docker/Dockerfile` — add `yaml-dev` and `pkgconf` packages for native extensions (Ruby 3.4 / psych). - `lib/seeders/reports/message_creator.rb` — add parentheses for clarity in range calculation. - `package.json` — pin Vite version and bump `vite-plugin-ruby`. - `pnpm-lock.yaml` — lockfile changes from JS dependency updates. - `spec/builders/v2/report_builder_spec.rb` — disable transactional fixtures; truncate tables per example via Rails `truncate_tables` so after_commit callbacks run with clean isolation; keep builder spec metadata minimal. - `spec/builders/v2/reports/label_summary_builder_spec.rb` — disable transactional fixtures + truncate tables via Rails `truncate_tables`; revert to real `resolved!`/`open!`/`resolved!` flow for multiple resolution events; align date range to `Time.zone` to avoid offset gaps; keep builder spec metadata minimal. - `spec/controllers/api/v1/accounts/macros_controller_spec.rb` — assert `assignee_id` instead of activity message to avoid transaction-timing flakes. - `spec/services/telegram/incoming_message_service_spec.rb` — reference the contact tied to the created conversation instead of `Contact.all.first` to avoid order-dependent failures when other specs leave data behind. - `spec/mailers/administrator_notifications/shared/smtp_config_shared.rb` — use `with_modified_env` instead of stubbing mailer internals. - `spec/services/account/sign_up_email_validation_service_spec.rb` — compare error `class.name` for parallel/reload-safe assertions. |
||
|
|
f9d1146cb0
|
feat: mensagens agendadas (#198)
* feat: Adds model for scheduling messages * feat: Implement scheduled message handling and processing jobs * feat: Add ScheduledMessagesController and associated specs for managing scheduled messages * refactor: Simplify scheduled message job specs and improve metadata handling * feat: Add ScheduledMessagePolicy for managing access to scheduled messages * feat: Add routes for managing scheduled messages * feat: Add scheduled message event handling and broadcasting * feat: Add JSON views for scheduled messages creation, destruction, updating, and indexing * feat: Update scheduled message status and dispatch update event after message creation * feat: Ensure scheduled message updates trigger dispatch event * feat: Add mutation types for managing scheduled messages * feat: Add additionalAttributes prop to Message component and provider * feat: Implement scheduled message handling in ActionCable and Vuex store * feat: Add unit tests for scheduled messages actions and mutations * feat: implement scheduled messages functionality - Added support for scheduling messages in the conversation dashboard. - Introduced new components: ScheduledMessageModal and ScheduledMessages for managing scheduled messages. - Enhanced ReplyBottomPanel to include scheduling options. - Updated Base.vue to handle scheduled message styling. - Integrated Vuex store module for managing scheduled messages state. - Added necessary translations for scheduled messages in English and Portuguese. * feat: add pagination to scheduled messages index and update tests accordingly * chore: update scheduled messages specs for future time validation and response status * chore: enhance scheduled messages API with pagination and add skeleton loader component * feat: add create_scheduled_message action to automation rule attributes * feat: implement create_scheduled_message action and enhance attachment handling * feat: add scheduled message functionality with UI components and localization * test: enhance scheduledMessages mutations tests with meta handling and structure * chore: update label to display file name upon successful upload in AutomationFileInput component * feat: add initialAttachment prop to ScheduledMessageModal and update ReplyBox to pass attachment * chore: prepend_mod_with to ScheduledMessagesController for better module handling * fix: attachment visibility in ScheduledMessageItem component * chore: enhance ScheduledMessage model with validations and reduce controller load * refactor: simplify ScheduledMessagesAPI methods by removing unnecessary instance variable * chore: update event emission for scheduled message creation in ReplyBox and ScheduledMessageModal * refactor: update status configuration to use label keys * chore: update date formatting in ScheduledMessageItem component * refactor: collapse logic to checkOverflow and update related functionality * chore: add author indication for current user in scheduled messages * chore: enhance scheduled message metadata with author information and localization * fix: send message shortcut * chore: handle errors in scheduled message submission * chore: update scheduled message modal to use combined date and time input * chore: refactor scheduled messages handling to remove pagination and update related tests * fix: ensure scheduled messages update status and dispatch on failure * fix: update scheduled message due date logic and simplify sending checks * refactor: rename build_message method for send_message * fix: update scheduled message creation time and improve test reliability * chore: ignore unnecessary check * chore: add scheduled message metadata handling in message builder, add scheduled message factorie and update specs * refactor: use scheduled message factorie creation in specs * chore: streamline error handling in scheduled message job and remove dispatch logic * fix: change scheduled_messages association to destroy dependent records * refactor: remove unused attributes from scheduled message payload builder * chore: update scheduled message retrieval to use conversation association * chore: correct cron format for scheduled messages job * chore: remove migration for author_type in scheduled_messages * feat: enhance scheduled messages management with delete confirmation and error handling * chore: set cron poll interval to 10 seconds for improved scheduling precision * feat: include additional_attributes in message JSON response * feat: enhance scheduled message validation and localization support * chore: update scheduled message display * Merge branch 'main' into Cayo-Oliveira/CU-86aenh268/Mensagens-agendadas * feat: add scheduled message indicators and validation for message length * fix: remove unnecessary condition from line-clamp class binding * feat: update scheduled messages localization and enhance content validation * feat: update scheduled messages order, enhance scheduledAt computation, and add message association * fix: reorder condition for Facebook channel message length computation * fix: change detection for attachments in scheduled messages * fix: remove unnecessary colon from close-on-backdrop-click prop in ScheduledMessageModal * chore: add error handling for scheduled message deletion and update localization for delete failure * fix: enforce minimum delay of 1 minute for scheduled messages and update validation * fix: remove unused private property and improve locale formatting for scheduled messages * fix: adjust positioning of DropdownBody in ReplyBottomPanel and clean up schema foreign keys * docs: add scheduled messages management APIs and payload definitions --------- Co-authored-by: gabrieljablonski <contact@gabrieljablonski.com> |
||
|
|
e9e6de5690
|
fix: Increase the parallelism config to fix flaky tests, revert bad commits (#13410)
The specs break only in Circle CI, we have to figure out the root cause for the same. At the moment, I have increased the parallelism to fix this. |
||
|
|
5ec77aca64
|
feat: Add first response time distribution report endpoint (#13400)
The index is already added in production.
Adds a new reporting API that returns conversation counts grouped by
channel type and first response time buckets (0-1h, 1-4h, 4-8h, 8-24h,
24h+).
- GET /api/v2/accounts/:id/reports/first_response_time_distribution
- Uses SQL aggregation to handle large datasets efficiently
- Adds composite index on reporting_events for query performance
Tested on production workload.
Request: GET
`/api/v2/accounts/1/reports/first_response_time_distribution?since=<since>&until=<until>`
Response payload:
```
{
"Channel::WebWidget": {
"0-1h": 120,
"1-4h": 85,
"4-8h": 32,
"8-24h": 12,
"24h+": 3
},
"Channel::Email": {
"0-1h": 12,
"1-4h": 28,
"4-8h": 45,
"8-24h": 35,
"24h+": 10
},
"Channel::FacebookPage": {
"0-1h": 50,
"1-4h": 30,
"4-8h": 15,
"8-24h": 8,
"24h+": 2
}
}
```
---------
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
|
||
|
|
b870a48734
|
perf: limit the number of notifications per user to 300 (#13234)
## Linear issue https://linear.app/chatwoot/issue/CW-6289/limit-the-number-of-notifications-per-user-to-300 ## Description Limits the number of notifications per user to 300 by introducing an async trim job that runs after each notification creation. This prevents unbounded notification growth that was causing DB CPU spikes. ## Type of change - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] This change requires a documentation update ## How Has This Been Tested? - Added unit tests for TrimUserNotificationsJob ## Checklist: - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my code - [ ] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Implements a dedicated purge job to control notification volume and scheduling. > > - Introduces `Notification::RemoveOldNotificationJob` (queue: `purgable`) to delete notifications older than 1 month and trim each user to the 300 most recent (deterministic by `created_at DESC, id DESC`) > - Adds daily cron (`remove_old_notification_job` at 22:30 UTC, queue `purgable`) in `config/schedule.yml` > - Removes ad-hoc triggering of the purge from `TriggerScheduledItemsJob` > - Adds/updates specs covering enqueue queue, old-notification deletion, per-user trimming, and combined behavior > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 9ea2b48e36df96cd15d4119d1dd7dcf5250695de. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Vishnu Narayanan <iamwishnu@gmail.com> Co-authored-by: Shivam Mishra <scm.mymail@gmail.com> |
||
|
|
6ab1898992 | Merge branch 'main' into chore/merge-upstream-4.10 | ||
|
|
d451615811
|
fix: prevent NoMethodError in mute helpers when contact is nil (#13277)
## Linear Ticket https://linear.app/chatwoot/issue/CW-4569/nomethoderror-undefined-method-blocked-for-nil-nomethoderror ## Description Fixes NoMethodError in ConversationMuteHelpers that occurs during contact deletion race condition. When a contact is deleted, there's a brief window (~50-150ms) where contact_id becomes nil but conversations still exist. If ResolutionJob runs during this window, the muted? method crashes trying to call blocked? on nil.Fixes # (issue) ## Type of change - [ ] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? - Created orphaned conversations (contact_id = nil) - Called muted?, mute!, unmute! - all return gracefully - Verified async deletion still works correctly ## Checklist: - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my code - [ ] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules Co-authored-by: Sojan Jose <sojan@pepalo.com> |
||
|
|
3c2d535de2
|
feat(webhook): retry job on 404 (#179)
* feat(webhook): retry job on 404 * feat(webhook): enhance retry logic for 404 errors and update message status * feat(webhook): update supported message events to use dynamic error handling * chore: refactor logic * feat(webhook): simplify RetriableError initialization and improve error handling for 404 responses |
||
|
|
549214e96d | Merge branch main into chore/merge-upstream | ||
|
|
ca5e112a8c
|
feat: TikTok channel (#12741)
fixes: #11834 This pull request introduces TikTok channel integration, enabling users to connect and manage TikTok business accounts similarly to other supported social channels. The changes span backend API endpoints, authentication helpers, webhook handling, configuration, and frontend components to support TikTok as a first-class channel. **Key Notes** * This integration is only compatible with TikTok Business Accounts * Special permissions are required to access the TikTok [Business Messaging API](https://business-api.tiktok.com/portal/docs?id=1832183871604753). * The Business Messaging API is region-restricted and is currently unavailable to users in the EU. * Only TEXT, IMAGE, and POST_SHARE messages are currently supported due to limitations in the TikTok Business Messaging API * A message will be successfully sent only if it contains text alone or one image attachment. Messages with multiple attachments or those combining text and attachments will fail and receive a descriptive error status. * Messages sent directly from the TikTok App will be synced into the system * Initiating a new conversation from the system is not permitted due to limitations from the TikTok Business Messaging API. **Backend: TikTok Channel Integration** * Added `Api::V1::Accounts::Tiktok::AuthorizationsController` to handle TikTok OAuth authorization initiation, returning the TikTok authorization URL. * Implemented `Tiktok::CallbacksController` to handle TikTok OAuth callback, process authorization results, create or update channel/inbox, and handle errors or denied scopes. * Added `Webhooks::TiktokController` to receive and verify TikTok webhook events, including signature verification and event dispatching. * Created `Tiktok::IntegrationHelper` module for JWT-based token generation and verification for secure TikTok OAuth state management. **Configuration and Feature Flags** * Added TikTok app credentials (`TIKTOK_APP_ID`, `TIKTOK_APP_SECRET`) to allowed configs and app config, and registered TikTok as a feature in the super admin features YAML. [[1]](diffhunk://#diff-5e46e1d248631a1147521477d84a54f8ba6846ea21c61eca5f70042d960467f4R43) [[2]](diffhunk://#diff-8bf37a019cab1dedea458c437bd93e34af1d6e22b1672b1d43ef6eaa4dcb7732R69) [[3]](diffhunk://#diff-123164bea29f3c096b0d018702b090d5ae670760c729141bd4169a36f5f5c1caR74-R79) **Frontend: TikTok Channel UI and Messaging Support** * Added `TiktokChannel` API client for frontend TikTok authorization requests. * Updated channel icon mappings and tests to include TikTok (`Channel::Tiktok`). [[1]](diffhunk://#diff-b852739ed45def61218d581d0de1ba73f213f55570aa5eec52aaa08f380d0e16R16) [[2]](diffhunk://#diff-3cd3ae32e94ef85f1f2c4435abf0775cc0614fb37ee25d97945cd51573ef199eR64-R69) * Enabled TikTok as a supported channel in contact forms, channel widgets, and feature toggles. [[1]](diffhunk://#diff-ec59c85e1403aaed1a7de35971fe16b7033d5cd763be590903ebf8f1ca25a010R47) [[2]](diffhunk://#diff-ec59c85e1403aaed1a7de35971fe16b7033d5cd763be590903ebf8f1ca25a010R69) [[3]](diffhunk://#diff-725b90ca7e3a6837ec8291e9f57094f6a46b3ee00e598d16564f77f32cf354b0R26-R29) [[4]](diffhunk://#diff-725b90ca7e3a6837ec8291e9f57094f6a46b3ee00e598d16564f77f32cf354b0R51-R54) [[5]](diffhunk://#diff-725b90ca7e3a6837ec8291e9f57094f6a46b3ee00e598d16564f77f32cf354b0R68) * Updated message meta logic to support TikTok-specific message statuses (sent, delivered, read). [[1]](diffhunk://#diff-e41239cf8dda36c1bd1066dbb17588ae8868e56289072c74b3a6d7ef5abdd696R23) [[2]](diffhunk://#diff-e41239cf8dda36c1bd1066dbb17588ae8868e56289072c74b3a6d7ef5abdd696L63-R65) [[3]](diffhunk://#diff-e41239cf8dda36c1bd1066dbb17588ae8868e56289072c74b3a6d7ef5abdd696L81-R84) [[4]](diffhunk://#diff-e41239cf8dda36c1bd1066dbb17588ae8868e56289072c74b3a6d7ef5abdd696L103-R107) * Added support for embedded message attachments (e.g., TikTok embeds) with a new `EmbedBubble` component and updated message rendering logic. [[1]](diffhunk://#diff-c3d701caf27d9c31e200c6143c11a11b9d8826f78aa2ce5aa107470e6fdb9d7fR31) [[2]](diffhunk://#diff-047859f9368a46d6d20177df7d6d623768488ecc38a5b1e284f958fad49add68R1-R19) [[3]](diffhunk://#diff-c3d701caf27d9c31e200c6143c11a11b9d8826f78aa2ce5aa107470e6fdb9d7fR316) [[4]](diffhunk://#diff-cbc85e7c4c8d56f2a847d0b01cd48ef36e5f87b43023bff0520fdfc707283085R52) * Adjusted reply policy and UI messaging for TikTok's 48-hour reply window. [[1]](diffhunk://#diff-0d691f6a983bd89502f91253ecf22e871314545d1e3d3b106fbfc76bf6d8e1c7R208-R210) [[2]](diffhunk://#diff-0d691f6a983bd89502f91253ecf22e871314545d1e3d3b106fbfc76bf6d8e1c7R224-R226) These changes collectively enable end-to-end TikTok channel support, from configuration and OAuth flow to webhook processing and frontend message handling. ------------ # TikTok App Setup & Configuration 1. Grant access to the Business Messaging API ([Documentation](https://business-api.tiktok.com/portal/docs?id=1832184145137922)) 2. Set the app authorization redirect URL to `https://FRONTEND_URL/tiktok/callback` 3. Update the installation config with TikTok App ID and Secret 4. Create a Business Messaging Webhook configuration and set the callback url to `https://FRONTEND_URL/webhooks/tiktok` ([Documentation](https://business-api.tiktok.com/portal/docs?id=1832190670631937)) . You can do this by calling `Tiktok::AuthClient.update_webhook_callback` from rails console once you finish Tiktok channel configuration in super admin ( will be automated in future ) 5. Enable TikTok channel feature in an account --------- Co-authored-by: Sojan Jose <sojan@pepalo.com> Co-authored-by: iamsivin <iamsivin@gmail.com> |
||
|
|
774c168d94
|
fix: z-api read message (#165)
* fix: z-api read messages * fix: use threads for parallel requests * feat: use jobs instead * fix: refactor ZapiReadMessageJob to use service method for sending read messages |
||
|
|
cc86b8c7f1
|
fix: stream attachment handling in workers (#12870)
We’ve been watching Sidekiq workers climb from ~600 MB at boot to 1.4–1.5 GB after an hour whenever attachment-heavy jobs run. This PR is an experiment to curb that growth by streaming attachments instead of loading the whole blob into Ruby: reply-mailer inline attachments, Telegram uploads, and audio transcriptions now read/write in chunks. If this keeps RSS stable in production we’ll keep it; otherwise we’ll roll it back and keep digging |
||
|
|
5c3b85334b
|
feat: Add support for shared post and story attachment types in Instagram messages (#12997)
When users share Instagram posts or stories via DM, Instagram sends webhooks with type `ig_post` and `ig_story` attachments. The system was failing on these types because they weren't defined in the file_types. This PR fixes the issue by handling all shared types and rendering them on the front end. **Shared post** <img width="2154" height="1828" alt="CleanShot 2025-12-03 at 16 29 14@2x" src="https://github.com/user-attachments/assets/7e731171-4904-43a6-abeb-b1db2c262742" /> **Shared status** <img width="1702" height="1676" alt="CleanShot 2025-12-03 at 16 10 25@2x" src="https://github.com/user-attachments/assets/6a151233-ce47-429d-b7c2-061514b20e05" /> Fixes https://linear.app/chatwoot/issue/CW-5441/argumenterror-ig-story-is-not-a-valid-file-type-argumenterror |
||
|
|
48627da0f9
|
feat: outbound voice call essentials (#12782)
- Enables outbound voice calls in voice channel . We are only caring about wiring the logic to trigger outgoing calls to the call button introduced in previous PRs. We will connect it to call component in subsequent PRs ref: #11602 ## Screens <img width="2304" height="1202" alt="image" src="https://github.com/user-attachments/assets/b91543a8-8d4e-4229-bd80-9727b42c7b0f" /> <img width="2304" height="1200" alt="image" src="https://github.com/user-attachments/assets/1a1dad2a-8cb2-4aa2-9702-c062416556a7" /> --------- Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Co-authored-by: iamsivin <iamsivin@gmail.com> Co-authored-by: Vishnu Narayanan <vishnu@chatwoot.com> |
||
|
|
b03dfdb751
|
Chore/merge upstream 4.8.0 (#150)
* chore: Hide "Learn More" button in feature spotlight for self-hosted (#12675) * feat: single query for reporting event stats (#12664) This PR collapses multiple queries fetching stats from a single table to a single query ```sql SELECT user_id as user_id, COUNT(CASE WHEN name = 'conversation_resolved' THEN 1 END) as resolved_count, AVG(CASE WHEN name = 'conversation_resolved' THEN value END) as avg_resolution_time, AVG(CASE WHEN name = 'first_response' THEN value END) as avg_first_response_time, AVG(CASE WHEN name = 'reply_time' THEN value END) as avg_reply_time FROM "reporting_events" WHERE "reporting_events"."account_id" = <account_id> AND "reporting_events"."created_at" >= '2025-09-14 18:30:00' AND "reporting_events"."created_at" < '2025-10-14 18:29:59' GROUP BY "reporting_events"."user_id"; ``` ### Why this works? Here's why this optimization is faster based on PostgreSQL internals: - Single Table Scan vs Multiple Scans: Earlier we did 4 sequential scans (or 4 index scans) of the same data, with the same where clause, now in a single scan all 4 `CASE` expressions are evaluated in a single pass. - Shared Buffer Cache Efficiency: PostgreSQL's shared buffer cache stores recently accessed pages, with this, pages are loaded once and re-used for all aggregation, earlier with separate queries we were forced to re-read all from the disk each time - Reduced planning and network overhead (4 vs 1 query) ### How is it tested 1. The specs all pass without making any changes 2. Verified the reports side by side after generating from report seeder #### How to test Generate seed data using the following command ```bash ACCOUNT_ID=1 ENABLE_ACCOUNT_SEEDING=true bundle exec rake db:seed:reports_data ``` Once done download the reports, checkout to this branch and download the reports again and compare them * chore: Update translations (#12625) * chore: Migrate mailers from the worker to jobs (#12331) Previously, email replies were handled inside workers. There was no execution logs. This meant if emails silently failed (as reported by a customer), we had no way to trace where the issue happened, the only assumption was “no error = mail sent.” By moving email handling into jobs, we now have proper execution logs for each attempt. This makes it easier to debug delivery issues and would have better visibility when investigating customer reports. Fixes https://linear.app/chatwoot/issue/CW-5538/emails-are-not-sentdelivered-to-the-contact --------- Co-authored-by: Sojan Jose <sojan@pepalo.com> Co-authored-by: Shivam Mishra <scm.mymail@gmail.com> * chore(deps-dev): bump vite from 5.4.20 to 5.4.21 (#12700) Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.20 to 5.4.21. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/vitejs/vite/releases">vite's releases</a>.</em></p> <blockquote> <h2>v5.4.21</h2> <p>Please refer to <a href="https://github.com/vitejs/vite/blob/v5.4.21/packages/vite/CHANGELOG.md">CHANGELOG.md</a> for details.</p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/vitejs/vite/blob/v5.4.21/packages/vite/CHANGELOG.md">vite's changelog</a>.</em></p> <blockquote> <h2><!-- raw HTML omitted -->5.4.21 (2025-10-20)<!-- raw HTML omitted --></h2> <ul> <li>fix(dev): trim trailing slash before <code>server.fs.deny</code> check (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/20968">#20968</a>) (<a href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/20970">#20970</a>) (<a href=" |
||
|
|
08b9134486
|
feat: speed up circleci and github actions (#12849)
# 🚀 Speed up CI/CD test execution with parallelization ## TL;DR - **Problem**: CI tests took 36-42 minutes per commit, blocking developer workflow - **Solution**: Implemented 16-way parallelization + optimized slow tests + fixed Docker builds - **Impact**: **1,358 hours/month saved** (7.7 FTE) across GitHub Actions + CircleCI - GitHub Actions tests: 36m → 7m (82% faster) - Backend tests: 28m → 4m (87% faster with 16-way parallelization) - CircleCI tests: 42m → 7m (83% faster) - Docker builds: 34m → 5m (85% faster) - **Result**: 5-6x faster feedback loops, 100% success rate on recent runs --- ## Problem CI test runs were taking **36-42 minutes per commit push** (GitHub Actions: 36m avg, CircleCI: 42m P95), creating a significant bottleneck in the development workflow. ## Solution This PR comprehensively restructures both CI test pipelines to leverage 16-way parallelization and optimize test execution, reducing test runtime from **36-42 minutes to ~7 minutes** - an **82% improvement**. --- ## 📊 Real Performance Data (Both CI Systems) ### GitHub Actions #### Before (develop branch - 5 recent runs) ``` Individual runs: 35m 29s | 36m 1s | 40m 0s | 36m 4s | 34m 18s Average: 36m 22s ``` #### After (feat/speed_up_ci branch - 9 successful runs) ``` Individual runs: 6m 39s | 7m 2s | 6m 53s | 6m 26s | 6m 52s | 6m 42s | 6m 45s | 6m 40s | 6m 37s Average: 6m 44s Range: 6m 26s - 7m 2s ``` **Improvement**: ⚡ **81.5% faster** (29m 38s saved per run) #### Backend Tests Specific Impact With 16-way parallelization, backend tests show dramatic improvement: - **Before**: 27m 52s (sequential execution) - **After**: 3m 44s (longest of 16 parallel runners) - Average across runners: 2m 30s - Range: 1m 52s - 3m 44s - **Improvement**: ⚡ **86.6% faster** (24m 8s saved) --- ### CircleCI #### Before (develop branch - CircleCI Insights) ``` Duration (P95): 41m 44s Runs: 70 (last 30 days) Success Rate: 84% ``` #### After (feat/speed_up_ci branch - Last 2 pipeline runs) ``` Run 1 (1h ago): 7m 7s ├─ lint: 4m 12s ├─ frontend-tests: 5m 36s ├─ backend-tests: 6m 23s ├─ coverage: 20s └─ build: 1s Run 2 (2h ago): 7m 21s ├─ lint: 3m 47s ├─ frontend-tests: 5m 4s ├─ backend-tests: 6m 33s ├─ coverage: 19s └─ build: 1s Average: 7m 14s Success Rate: 100% ✅ ``` **Improvement**: ⚡ **82.7% faster** (34m 30s saved per run) --- ## 🐳 Related Work: Docker Build Optimization As part of the broader CI/CD optimization effort, Docker build performance was improved separately in **PR #12859**. ### Docker Build Fix (Merged Separately) **Problem**: Multi-architecture Docker builds (amd64/arm64) were taking ~34 minutes due to cache thrashing **Solution**: Added separate cache scopes per platform in `.github/workflows/test_docker_build.yml`: ```yaml cache-from: type=gha,scope=${{ matrix.platform }} cache-to: type=gha,mode=max,scope=${{ matrix.platform }} ``` **Results** (measured from November 2025 data): - **Before**: 34.2 minutes/run average (15,547 minutes across 454 runs) - **After**: 5 minutes/run - **Improvement**: 85% faster, 29.2 minutes saved per run - **Frequency**: 25.2 runs/day - **Monthly savings**: **369 hours** (46 developer-days) This prevents different architectures from invalidating each other's caches and contributes 27% of total CI/CD time savings. --- ## 🎯 Key Findings ### Both CI Systems Now Perform Similarly - **CircleCI**: 7m 14s average - **GitHub Actions**: 6m 44s average - **Difference**: Only 30 seconds apart (remarkably consistent!) ### Combined Performance - **Average improvement across both systems**: **82.1% faster** - **Time saved per commit**: ~32 minutes - **Developer feedback loop**: 36-42 minutes → ~7 minutes ### Success Rate Improvement - **CircleCI**: 84% → 100% (on feat/speed_up_ci branch) - **GitHub Actions**: 100% (all 9 recent runs successful) - Fixed all test isolation issues that caused intermittent failures ### Impact at Scale (Based on Real November 2025 Data) - **CI runs per day**: **30.8 average** for tests, **25.2** for Docker builds - Measured from GitHub Actions Usage Metrics (18 days) - Weekdays: 38-54 runs/day - Peak: up to 68 runs in a single day - **This PR (test suite only)**: - **Daily time saved**: **15.3 hours** (GitHub Actions + CircleCI) - **Monthly time saved**: **458 hours** (57 developer-days) on GitHub Actions - Additional **531 hours** (66 developer-days) on CircleCI - **Combined with Docker optimization** (PR #12859): **1,358 hours/month** (see Summary) - **Developer experience**: 5-6x faster iteration cycles --- ## Code Changes ### 1. **Backend Test Parallelization (16x)** Both CI systems now use 16-way parallelization with identical round-robin test distribution: ```bash # Distribute tests evenly across 16 runners SPEC_FILES=($(find spec -name '*_spec.rb' | sort)) for i in "${!SPEC_FILES[@]}"; do if [ $(( i % 16 )) -eq $RUNNER_INDEX ]; then TESTS="$TESTS ${SPEC_FILES[$i]}" fi done ``` **Why round-robin over timing-based?** - CircleCI's timing-based splitting grouped similar tests together - This caused race conditions with OAuth callback tests (Linear, Shopify, Notion) - Round-robin ensures even distribution and better test isolation - Both CI systems now behave identically ### 2. **Frontend Test Optimization** Enabled Vitest thread parallelization in `vite.config.ts`: ```typescript pool: 'threads', poolOptions: { threads: { singleThread: false, }, }, ``` ### 3. **CI Architecture Restructuring** Split monolithic CI jobs into parallel stages: - **Lint** (backend + frontend) - runs independently for fast feedback - **Frontend tests** - runs in parallel with backend - **Backend tests** - 16-way parallelized across runners - **Coverage** - aggregates results from test jobs - **Build** (CircleCI only) - final job for GitHub status check compatibility ### 4. **Critical Test Optimization** **report_builder_spec.rb**: Changed `before` to `before_all` - Reduced execution time from **19 minutes to 1.2 minutes** (16x speedup) - Setup now runs once instead of 21 times - Single biggest performance improvement after parallelization --- ## Test Stability Fixes (10 spec files) Parallelization exposed latent test isolation issues that were fixed: ### Object Identity Comparisons (6 files) Tests were comparing Ruby object instances instead of IDs: - `spec/models/integrations/hook_spec.rb` - Use `.pluck(:id)` for comparisons - `spec/enterprise/models/captain/scenario_spec.rb` - Compare IDs instead of objects - `spec/models/notification_spec.rb` - Compare IDs for sort order validation - `spec/models/account_spec.rb` - Compare IDs in scope queries - `spec/services/widget/token_service_spec.rb` - Compare class names instead of class objects - `spec/models/concerns/avatarable_shared.rb` - Use `respond_to` checks for ActiveStorage ### Database Query Caching - `spec/jobs/delete_object_job_spec.rb` - Added `.reload` to force fresh database queries ### Test Expectations Timing - `spec/jobs/mutex_application_job_spec.rb` - Removed flaky unlock expectation after error block - Related to original PR #8770 - Expectation after error block never executes in parallel environments ### Timezone Handling - `spec/mailers/account_notification_mailer_spec.rb` - Fixed date parsing at timezone boundaries - Changed test time from 23:59:59Z to 12:00:00Z ### Test Setup - `spec/builders/v2/report_builder_spec.rb` - Optimized with `before_all` --- ## CircleCI GitHub Integration Fix ### Problem GitHub PR checks were stuck on "Waiting for status" even when all CircleCI jobs passed. GitHub was expecting a job named `build` but the workflow only had a workflow named "build". ### Solution Added an explicit `build` job that runs after all other jobs: ```yaml build: steps: - run: name: Legacy build aggregator command: echo "All main jobs passed" requires: - lint - coverage ``` This ensures GitHub's required status checks work correctly. --- ## ✅ Testing & Validation - ✅ **GitHub Actions**: 9 successful runs, consistent 6m 26s - 7m 2s runtime - ✅ **CircleCI**: 2 successful runs, consistent 7m 7s - 7m 21s runtime - ✅ Both CI systems produce identical, consistent results - ✅ GitHub PR status checks complete correctly - ✅ Success rate improved from 84% to 100% (recent runs) - ✅ No test regressions introduced - ✅ All flaky tests fixed (callback controllers, mutex jobs, etc.) --- ## 🎉 Summary This PR delivers an **82% improvement** in test execution time across both CI systems: - **GitHub Actions tests**: 36m → 7m (81.5% faster) - Backend tests specifically: 28m → 4m (86.6% faster) - **CircleCI tests**: 42m → 7m (82.7% faster) - **Developer feedback loop**: 5-6x faster - **Test stability**: 84% → 100% success rate ### 📊 Total CI/CD Impact (All Optimizations) Based on real November 2025 data, combining this PR with Docker build optimization (PR #12859): **Monthly Time Savings**: **1,358 hours/month** = **170 developer-days/month** = **7.7 FTE** | System | Runs/Day | Before | After | Savings | Monthly Impact | |--------|----------|---------|--------|---------|----------------| | **GitHub Actions Tests** | 30.8 | 36.5m | 6.7m | 29.8m/run | 458 hrs (34%) | | **GitHub Actions Docker** | 25.2 | 34.2m | 5.0m | 29.2m/run | 369 hrs (27%) | | **CircleCI Tests** | 30.8 | 41.7m | 7.2m | 34.5m/run | 531 hrs (39%) | *Data source: GitHub Actions Usage Metrics (November 2025, 18 days), CircleCI Insights (30 days)* The combined optimizations save the equivalent of **nearly 8 full-time developers** worth of CI waiting time every month, significantly improving developer velocity and reducing CI costs. All test isolation issues exposed by parallelization have been fixed, ensuring reliable and consistent results across both CI platforms. woot woot !!! --------- |
||
|
|
c9823d9409
|
feat: Assignment service (v2) (#12320)
## Linear Link ## Description This PR introduces a new robust auto-assignment system for conversations in Chatwoot. The system replaces the existing round-robin assignment with a more sophisticated service-based architecture that supports multiple assignment strategies, rate limiting, and Enterprise features like capacity-based assignment and balanced distribution. ## Type of change - [ ] New feature (non-breaking change which adds functionality) ## How Has This Been Tested? - Unit test cases - Test conversations getting assigned on status change to open - Test the job directly via rails console ## Checklist: - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my code - [ ] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Adds a new service-based auto-assignment system with scheduled jobs, rate limiting, enterprise capacity/balanced selection, and wiring via inbox/handler; includes Redis helpers and comprehensive tests. > > - **Auto-assignment v2 (core services)**: > - Add `AutoAssignment::AssignmentService` with bulk assignment, configurable conversation priority, RR selection, and per-agent rate limiting via `AutoAssignment::RateLimiter`. > - Add `AutoAssignment::RoundRobinSelector` for agent selection. > - **Jobs & scheduling**: > - Add `AutoAssignment::AssignmentJob` (per-inbox bulk assign; env-based limit) and `AutoAssignment::PeriodicAssignmentJob` (batch over accounts/inboxes). > - Schedule periodic run in `config/schedule.yml` (`periodic_assignment_job`). > - **Model/concerns wiring**: > - Include `InboxAgentAvailability` in `Inbox`; add `Inbox#auto_assignment_v2_enabled?`. > - Update `AutoAssignmentHandler` to trigger v2 job when `auto_assignment_v2_enabled?`, else fallback to legacy. > - **Enterprise extensions**: > - Add `Enterprise::InboxAgentAvailability` (capacity-aware filtering) and `Enterprise::Concerns::Inbox` association `inbox_capacity_limits`. > - Extend service via `Enterprise::AutoAssignment::AssignmentService` (policy-driven config, capacity filtering, exclusion rules) and add selectors/services: `BalancedSelector`, `CapacityService`. > - **Infrastructure**: > - Enhance `Redis::Alfred` with `expire`, key scan/count, and extended ZSET helpers (`zadd`, `zcount`, `zcard`, `zrangebyscore`). > - **Tests**: > - Add specs for jobs, core service, rate limiter, RR selector, and enterprise features (capacity, balanced selection, exclusions). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 0ebe187c8aea73765b0122a44b18d6f465c2477f. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com> Co-authored-by: Shivam Mishra <scm.mymail@gmail.com> |
||
|
|
63a2c70667
|
fix(zapi): first connection issues, and merge existing contact on received message (#138)
* fix(zapi): pairing issues on first connection * fix(zapi): handle existing contact when receiving new message * refactor: simplify logic |
||
|
|
159c810117
|
feat: Bulk actions for contacts (#12763)
Introduces APIs and UI for bulk actions in contacts table. The initial action available will be assign labels Fixes: #8536 #12253 ## Screens <img width="1350" height="747" alt="Screenshot 2025-10-29 at 4 05 08 PM" src="https://github.com/user-attachments/assets/0792dff5-0371-4b2e-bdfb-cd32db773402" /> <img width="1345" height="717" alt="Screenshot 2025-10-29 at 4 05 19 PM" src="https://github.com/user-attachments/assets/ae510404-c6de-4c15-a720-f6d10cdac25b" /> --------- Co-authored-by: Muhsin <muhsinkeramam@gmail.com> Co-authored-by: iamsivin <iamsivin@gmail.com> Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> |
||
|
|
eabdfc8168
|
chore(sidekiq): log ActiveJob class and job_id on dequeue (#12704)
## Context Sidekiq logs only showed the Sidekiq wrapper class and JID, which wasn’t helpful when debugging ActiveJobs. ## Changes - Updated `ChatwootDequeuedLogger` to log the actual `ActiveJob class` and `job_id` instead of the generic Sidekiq wrapper and JID. > Example > ``` > Dequeued ActionMailer::MailDeliveryJob 123e4567-e89b-12d3-a456-426614174000 from default > ``` - Remove sidekiq worker and unify everything to `ActiveJob` |
||
|
|
254d5dcf9a
|
chore: Migrate mailers from the worker to jobs (#12331)
Previously, email replies were handled inside workers. There was no execution logs. This meant if emails silently failed (as reported by a customer), we had no way to trace where the issue happened, the only assumption was “no error = mail sent.” By moving email handling into jobs, we now have proper execution logs for each attempt. This makes it easier to debug delivery issues and would have better visibility when investigating customer reports. Fixes https://linear.app/chatwoot/issue/CW-5538/emails-are-not-sentdelivered-to-the-contact --------- Co-authored-by: Sojan Jose <sojan@pepalo.com> Co-authored-by: Shivam Mishra <scm.mymail@gmail.com> |
||
|
|
8d4a6b856a | Merge branch main into chore/merge-upstream-4.7.0 | ||
|
|
4fc80ba4ee
|
feat(zapi): Z-API integration (#115)
* feat(zapi): connect flow and UI updates * fix(zapi): re-add manage connection section * feat(zapi): reply * feat: send message * fix: qrcode job logic * test: qr code job specs * chore: concurrent index * chore: whatsapp model minor * test: message window service specs * chore: service refactor * test: zapi service * chore: zapi beta * chore: minor fixes * test: incoming message specs * chore: minor fixes * feat: handle status transitions * test: refactor spec * test: refactor spec * chore(z-api): use feature flag * chore: fix migration name |
||
|
|
b75ea7a762
|
feat: Use resolved contacts as base relation for filtering (#12520)
This PR has two changes to speed up contact filtering ### Updated Base Relation Update the `base_relation` to use resolved contacts scope to improve perf when filtering conversations. This narrows the search space drastically, and what is usually a sequential scan becomes a index scan for that `account_id` ref: https://github.com/chatwoot/chatwoot/pull/9347 ref: https://github.com/chatwoot/chatwoot/pull/7175/ Result: https://explain.dalibo.com/plan/c8a8gb17f0275fgf#plan ## Selective filtering in Compose New Conversation We also cost of filtering in compose new conversation dialog by reducing the search space based on the search candidate. For instance, a search term that obviously can’t be a phone, we exclude that from the filter. Similarly we skip name lookups for email-shaped queries. Removing the phone number took the query times from 50 seconds to under 1 seconds ### Comparison 1. Only Email: https://explain.dalibo.com/plan/h91a6844a4438a6a 2. Email + Name: https://explain.dalibo.com/plan/beg3aah05ch9ade0 3. Email + Name + Phone: https://explain.dalibo.com/plan/c8a8gb17f0275fgf |
||
|
|
24620a0baf | chore: apply rubocop | ||
|
|
18c672c204 | Merge branch 'main' into chore/merge-upstream-4.6.0 | ||
|
|
55315089cf
|
fix(delete_object_job): pre-purge heavy associations before destroy to prevent timeout (#12408)
Deleting large Accounts/Inboxes with object.destroy! can time out and create heavy destroy_async fan-out; this change adds a simple pre-purge that batch-destroys heavy associations first . ``` Account: conversations, contacts Inbox: conversations, contact_inboxes ``` We use find_in_batches(5000), then proceeds with destroy!, reducing DB pressure and race conditions while preserving callbacks and leaving the behavior for non heavy models unchanged. The change is also done in a way to easily add additional objects or relations to the list. fixes: https://linear.app/chatwoot/issue/CW-3106/inbox-deletion-process-update-the-flow |
||
|
|
81b401c998
|
fix: Add URL validation and rate limiting for contact avatar sync (#11979)
- Implement 1-minute rate limiting for contacts to prevent bombardment - Add URL hash comparison to sync only when avatar URL changes |
||
|
|
f4643116df
|
feat: Run assignment every 15 minutes (#12334)
Currently, auto-assignment runs only during conversation creation or update events. If no agents are online when new conversations arrive, those conversations remain unassigned. With this change, unassigned conversations will be automatically assigned once agents become available. The job runs every 15 minutes and uses a fair distribution threshold of 100 to prevent a large number of conversations from being assigned to a single available agent. This will be customizable later. |
||
|
|
dbb41df67e
|
fix: update GitHub versions link and version fetching (#105)
* fix: update GitHub versions link and version fetching * test: specs * chore: use timeout and log error * refactor: redundant helper method |
||
|
|
7d6a43fc72
|
feat: Added the backend support for twilio content templates (#12272)
Added comprehensive Twilio WhatsApp content template support (Phase 1)
enabling text, media, and quick reply templates with proper parameter
conversion, sync capabilities.
**Template Types Supported**
- Basic Text Templates: Simple text with variables ({{1}}, {{2}})
- Media Templates: Image/Video/Document templates with text variables
- Quick Reply Templates: Interactive button templates
Front end changes is available via #12277
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
|
||
|
|
801033bd5f | Merge branch 'main' into chore/merge-upstream-4.5.0 | ||
|
|
ad4ec9e93b
|
fix: Flaky Instagram webhook specs (#12170)
### Summary
Fixed flaky Instagram webhook specs that failed intermittently in cloud
environments due to shared let blocks creating conflicting inboxes. The
Instagram channel factory already creates an inbox automatically, but
tests were adding extra ones in shared contexts.
Moved channel/inbox creation to isolated test contexts to prevent race
conditions between Facebook Page and Instagram Direct tests.
### Testing
```
for i in {1..30}; do
echo "=== Run $i ==="
RAILS_ENV=test bundle exec rspec spec/jobs/webhooks/instagram_events_job_spec.rb --fail-fast || break
done
```
Previously, intermittent failures could be reproduced locally. With
these changes, tests achieve ~100% pass rate.
|
||
|
|
c31325e982
|
fix: resolve mutex conflicts in Instagram webhook specs (#12154)
This PR fixes flaky test failures in the Instagram webhook specs that were caused by Redis mutex lock conflicts when tests ran in parallel. ### The Problem: The InstagramEventsJob uses a Redis mutex with a key based on sender_id and ig_account_id to prevent race conditions. However, all test factories were using the same hardcoded sender_id: 'Sender-id-1', causing multiple test instances to compete for the same mutex lock when running in parallel. ### The Solution: - Updated all Instagram event factories to generate unique sender IDs using SecureRandom.hex(4) - Modified test stubs and expectations to work with dynamic sender IDs instead of hardcoded values - Ensured each test instance gets its own unique mutex key, eliminating lock contention |
||
|
|
51b9fd8eca
|
fix: Disable IMAP inboxes that requires authorization (#12092)
This PR disables queueing IMAP sync jobs for emails channels that - are in free plan if on Chatwoot cloud. - requires authorization |
||
|
|
cbc2807296
|
fix: Creates contact when Instagram returns No matching Instagram user (#11496)
# Creates contact when Instagram returns `No matching Instagram user`
## Description
The error occurs when Facebook tries to validate the Facebook App
created to authorize Instagram integration.
The Facebook's agent uses a Bot to make tests on the App where is not a
valid user via API, returning `{"error"=>{"message"=>"No matching
Instagram user", "type"=>"IGApiException", "code"=>9010}}`.
Then Facebook rejects the request saying this app is still not ready
once the integration with Instagram didn't work.
We can safely create an unknown contact, making this integration work.
## Type of change
Please delete options that are not relevant.
- [X] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [ ] This change requires a documentation update
## How Has This Been Tested?
There's automated test to cover.
## Checklist:
- [X] My code follows the style guidelines of this project
- [X] I have performed a self-review of my code
- [X] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [X] I have added tests that prove my fix is effective or that my
feature works
- [X] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
---------
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
|
||
|
|
2cf1795a3b
|
feat: baileys connection period check (#87)
* feat: periodic check for baileys connection * chore: add index on provider connection |
||
|
|
9acb0d86b5
|
fix: Disable enqueueing Avatar jobs if the URL is invalid (#12035)
- Add a new queue purgable - Disable enqueuing the job if URL is invalid |
||
|
|
4f0b5cd595 | Merge branch 'main' into chatwoot/develop | ||
|
|
6b8dd3c86a
|
chore: move UpdateMessageStatus to deferred queue (#11943)
- move `UpdateMessageStatus` to `deferred` queue below `scheduled_jobs` --------- Co-authored-by: Pranav <pranav@chatwoot.com> Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com> |
||
|
|
b1893c7d96
|
fix: Support location messages in Twilio WhatsApp integration (#11830)
Fixes location messages not appearing in conversations when sent via Twilio. Location messages were being filtered out due to empty body content and missing parameter handling.  |
||
|
|
288df3a399
|
fix: Flaky Instagram unsend message test (#11712)
- Use direct message object reference instead of re-querying through inbox - Add message.reload after unsend operation to get updated state - Remove unnecessary inbox reload that could cause timing issues - Remove redundant assertions for better test atomicity Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com> |
||
|
|
3d543ea19b | chore: apply linter | ||
|
|
fab34768e2 | Merge branch 'main' into chore/merge-upstream | ||
|
|
e9a132a923
|
feat: auto resolve label option and fixes (#11541)
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com> |
||
|
|
0317803b7c | Merge branch 'main' into chore/merge-upstream |