diff --git a/Gemfile b/Gemfile index 5b03b771b..711e744c3 100644 --- a/Gemfile +++ b/Gemfile @@ -85,6 +85,8 @@ gem 'sentry-raven' ##-- background job processing --## gem 'sidekiq' +# We want cron jobs +gem 'sidekiq-cron' ##-- Push notification service --## gem 'fcm' diff --git a/Gemfile.lock b/Gemfile.lock index b6a773967..e0b382569 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -182,6 +182,8 @@ GEM railties (>= 3.2) equalizer (0.0.11) erubi (1.9.0) + et-orbi (1.2.4) + tzinfo execjs (2.7.0) facebook-messenger (1.5.0) httparty (~> 0.13, >= 0.13.7) @@ -202,6 +204,9 @@ GEM ffi (1.14.2) flag_shih_tzu (0.3.23) foreman (0.87.2) + fugit (1.4.1) + et-orbi (~> 1.1, >= 1.1.8) + raabro (~> 1.4) geocoder (1.6.3) gli (2.19.2) globalid (0.4.2) @@ -337,6 +342,7 @@ GEM nio4r (~> 2.0) pundit (2.1.0) activesupport (>= 3.0.0) + raabro (1.4.0) racc (1.5.2) rack (2.2.3) rack-cache (1.12.0) @@ -476,6 +482,9 @@ GEM connection_pool (>= 2.2.2) rack (~> 2.0) redis (>= 4.2.0) + sidekiq-cron (1.2.0) + fugit (~> 1.1) + sidekiq (>= 4.2.1) signet (0.14.0) addressable (~> 2.3) faraday (>= 0.17.3, < 2.0) @@ -635,6 +644,7 @@ DEPENDENCIES sentry-raven shoulda-matchers sidekiq + sidekiq-cron simplecov (= 0.17.1) slack-ruby-client spring diff --git a/app/jobs/internal/check_new_versions_job.rb b/app/jobs/internal/check_new_versions_job.rb new file mode 100644 index 000000000..9f54b0ddd --- /dev/null +++ b/app/jobs/internal/check_new_versions_job.rb @@ -0,0 +1,12 @@ +class Internal::CheckNewVersionsJob < ApplicationJob + queue_as :scheduled_jobs + + def perform + return unless Rails.env.production? + + latest_version = ChatwootHub.latest_version + return unless latest_version + + ::Redis::Alfred.set(::Redis::Alfred::LATEST_CHATWOOT_VERSION, latest_version) + end +end diff --git a/app/workers/conversation_reply_email_worker.rb b/app/workers/conversation_reply_email_worker.rb index da6e18fe0..d0c1311fd 100644 --- a/app/workers/conversation_reply_email_worker.rb +++ b/app/workers/conversation_reply_email_worker.rb @@ -1,3 +1,4 @@ +# TODO: lets move this to active job, since thats what we use over all class ConversationReplyEmailWorker include Sidekiq::Worker sidekiq_options queue: :mailers diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index 7a28ca972..f3ba72aef 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -1,3 +1,5 @@ +schedule_file = 'config/schedule.yml' + Sidekiq.configure_client do |config| config.redis = Redis::Config.sidekiq end @@ -5,3 +7,6 @@ end Sidekiq.configure_server do |config| config.redis = Redis::Config.sidekiq end + +# https://github.com/ondrejbartas/sidekiq-cron +Sidekiq::Cron::Job.load_from_hash YAML.load_file(schedule_file) if File.exist?(schedule_file) && Sidekiq.server? diff --git a/config/routes.rb b/config/routes.rb index 1b461fa95..3d74fe877 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -189,6 +189,7 @@ Rails.application.routes.draw do # ---------------------------------------------------------------------- # Internal Monitoring Routes require 'sidekiq/web' + require 'sidekiq/cron/web' devise_for :super_admins, path: 'super_admin', controllers: { sessions: 'super_admin/devise/sessions' } devise_scope :super_admin do diff --git a/config/schedule.yml b/config/schedule.yml new file mode 100644 index 000000000..b5ae49733 --- /dev/null +++ b/config/schedule.yml @@ -0,0 +1,8 @@ +# https://github.com/ondrejbartas/sidekiq-cron +# use https://crontab.guru/ to validate + +# executed At 12:00 on every day-of-month. +internal_check_new_versions_job: + cron: "0 12 */1 * *" + class: "Internal::CheckNewVersionsJob" + queue: scheduled_jobs diff --git a/config/sidekiq.yml b/config/sidekiq.yml index 3e20bd0df..c158e7202 100644 --- a/config/sidekiq.yml +++ b/config/sidekiq.yml @@ -12,11 +12,12 @@ # http://www.mikeperham.com/2013/11/13/advanced-sidekiq-host-specific-queues/ :queues: - [low, 1] + - [scheduled_jobs, 1] - [webhooks, 1] - - [integrations, 2] - [bots, 1] - [active_storage_analysis, 1] - [action_mailbox_incineration, 1] + - [integrations, 2] - [default, 2] - [mailers, 2] - [medium, 3] diff --git a/lib/chatwoot_hub.rb b/lib/chatwoot_hub.rb new file mode 100644 index 000000000..69e95ad9f --- /dev/null +++ b/lib/chatwoot_hub.rb @@ -0,0 +1,22 @@ +class ChatwootHub + BASE_URL = 'https://hub.chatwoot.com'.freeze + + def self.instance_config + { + installationVersion: Chatwoot.config[:version], + installationHost: URI.parse(ENV.fetch('FRONTEND_URL', '')).host + } + end + + def self.latest_version + begin + response = RestClient.get(BASE_URL, { params: instance_config }) + version = JSON.parse(response)['version'] + rescue *ExceptionList::REST_CLIENT_EXCEPTIONS, *ExceptionList::URI_EXCEPTIONS => e + Rails.logger.info "Exception: #{e.message}" + rescue StandardError => e + Raven.capture_exception(e) + end + version + end +end diff --git a/lib/redis/redis_keys.rb b/lib/redis/redis_keys.rb index 454a3715a..cef29705c 100644 --- a/lib/redis/redis_keys.rb +++ b/lib/redis/redis_keys.rb @@ -25,4 +25,7 @@ module Redis::RedisKeys # Used to track token expiry and such issues for facebook slack integrations etc AUTHORIZATION_ERROR_COUNT = 'AUTHORIZATION_ERROR_COUNT:%s:%d'.freeze REAUTHORIZATION_REQUIRED = 'REAUTHORIZATION_REQUIRED:%s:%d'.freeze + + ## Internal Installation related keys + LATEST_CHATWOOT_VERSION = 'LATEST_CHATWOOT_VERSION'.freeze end diff --git a/spec/jobs/internal/check_new_versions_job_spec.rb b/spec/jobs/internal/check_new_versions_job_spec.rb new file mode 100644 index 000000000..853241835 --- /dev/null +++ b/spec/jobs/internal/check_new_versions_job_spec.rb @@ -0,0 +1,14 @@ +require 'rails_helper' + +RSpec.describe Internal::CheckNewVersionsJob, type: :job do + subject(:job) { described_class.perform_now } + + it 'updates the latest chatwoot version in redis' do + version = '1.1.1' + allow(Rails.env).to receive(:production?).and_return(true) + allow(ChatwootHub).to receive(:latest_version).and_return(version) + job + expect(ChatwootHub).to have_received(:latest_version) + expect(::Redis::Alfred.get(::Redis::Alfred::LATEST_CHATWOOT_VERSION)).to eq version + end +end diff --git a/spec/lib/chatwoot_hub_spec.rb b/spec/lib/chatwoot_hub_spec.rb new file mode 100644 index 000000000..26d75365f --- /dev/null +++ b/spec/lib/chatwoot_hub_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +describe ChatwootHub do + it 'get latest version from chatwoot hub' do + version = '1.1.1' + allow(RestClient).to receive(:get).and_return({ 'version': version }.to_json) + expect(described_class.latest_version).to eq version + expect(RestClient).to have_received(:get).with(described_class::BASE_URL, { params: described_class.instance_config }) + end + + it 'returns nil when chatwoot hub is down' do + allow(RestClient).to receive(:get).and_raise(ExceptionList::REST_CLIENT_EXCEPTIONS.sample) + expect(described_class.latest_version).to eq nil + end +end