From b5fbab0e31691eab802c0c7b6a2a0bbb23075274 Mon Sep 17 00:00:00 2001 From: Mac Siri Date: Fri, 9 Dec 2022 10:46:20 -0500 Subject: [PATCH] Update ArticleFetchedFeed to use slack workflow (#18801) --- app/services/feeds/import.rb | 3 +- .../slack/messengers/article_fetched_feed.rb | 34 -------------- app/services/slack/workflow_webhook.rb | 14 ++++++ app/workers/slack/workflow_webhook_worker.rb | 11 +++++ spec/services/feeds/import_spec.rb | 6 +-- .../messengers/article_fetched_feed_spec.rb | 45 ------------------- spec/services/slack/workflow_webhook_spec.rb | 24 ++++++++++ .../slack/workflow_webhook_worker_spec.rb | 21 +++++++++ 8 files changed, 74 insertions(+), 84 deletions(-) delete mode 100644 app/services/slack/messengers/article_fetched_feed.rb create mode 100644 app/services/slack/workflow_webhook.rb create mode 100644 app/workers/slack/workflow_webhook_worker.rb delete mode 100644 spec/services/slack/messengers/article_fetched_feed_spec.rb create mode 100644 spec/services/slack/workflow_webhook_spec.rb create mode 100644 spec/workers/slack/workflow_webhook_worker_spec.rb diff --git a/app/services/feeds/import.rb b/app/services/feeds/import.rb index bf86338b2..699619fb5 100644 --- a/app/services/feeds/import.rb +++ b/app/services/feeds/import.rb @@ -48,8 +48,6 @@ module Feeds total_articles_count += articles.length - articles.each { |article| Slack::Messengers::ArticleFetchedFeed.call(article: article) } - # we use `feed_fetched_at` to mark the last time a particular user's feed has been fetched, parsed and imported batch_of_users.update_all(feed_fetched_at: Time.current) end @@ -169,6 +167,7 @@ module Feeds next end + Slack::WorkflowWebhookWorker.perform_async("Imported #{articles.length} articles for #{user.username}") articles end diff --git a/app/services/slack/messengers/article_fetched_feed.rb b/app/services/slack/messengers/article_fetched_feed.rb deleted file mode 100644 index e24122626..000000000 --- a/app/services/slack/messengers/article_fetched_feed.rb +++ /dev/null @@ -1,34 +0,0 @@ -module Slack - module Messengers - class ArticleFetchedFeed - def initialize(article:) - @article = article - end - - def self.call(...) - new(...).call - end - - def call - return unless article.published_from_feed? - - message = I18n.t( - "services.slack.messengers.article_fetched_feed.body", - title: article.title, - url: URL.article(article), - ) - - Slack::Messengers::Worker.perform_async( - "message" => message, - "channel" => "activity", - "username" => "article_bot", - "icon_emoji" => ":robot_face:", - ) - end - - private - - attr_reader :article - end - end -end diff --git a/app/services/slack/workflow_webhook.rb b/app/services/slack/workflow_webhook.rb new file mode 100644 index 000000000..c51f4e71b --- /dev/null +++ b/app/services/slack/workflow_webhook.rb @@ -0,0 +1,14 @@ +module Slack + module WorkflowWebhook + def self.call(message) + return if ApplicationConfig["SLACK_WORKFLOW_WEBHOOK_URL"].blank? + return if message.blank? + + HTTParty.post( + ApplicationConfig["SLACK_WORKFLOW_WEBHOOK_URL"], + body: { message: message }.to_json, + headers: { "Content-Type" => "application/json" }, + ) + end + end +end diff --git a/app/workers/slack/workflow_webhook_worker.rb b/app/workers/slack/workflow_webhook_worker.rb new file mode 100644 index 000000000..5a1afe974 --- /dev/null +++ b/app/workers/slack/workflow_webhook_worker.rb @@ -0,0 +1,11 @@ +module Slack + class WorkflowWebhookWorker + include Sidekiq::Job + + sidekiq_options queue: :low_priority, retry: 10 + + def perform(message) + Slack::WorkflowWebhook.call(message) + end + end +end diff --git a/spec/services/feeds/import_spec.rb b/spec/services/feeds/import_spec.rb index b0f8ac8b1..0b1dcaeaa 100644 --- a/spec/services/feeds/import_spec.rb +++ b/spec/services/feeds/import_spec.rb @@ -57,9 +57,9 @@ RSpec.describe Feeds::Import, type: :service, vcr: true do end it "queues as many slack messages as there are articles", vcr: { cassette_name: "feeds_import" } do - old_count = Slack::Messengers::Worker.jobs.count - num_articles = described_class.call - expect(Slack::Messengers::Worker.jobs.count).to eq(old_count + num_articles) + expect do + described_class.call + end.to change(Slack::WorkflowWebhookWorker.jobs, :count).by(3) # 3 users end context "when handling errors", vcr: { cassette_name: "feeds_import" } do diff --git a/spec/services/slack/messengers/article_fetched_feed_spec.rb b/spec/services/slack/messengers/article_fetched_feed_spec.rb deleted file mode 100644 index db5b66443..000000000 --- a/spec/services/slack/messengers/article_fetched_feed_spec.rb +++ /dev/null @@ -1,45 +0,0 @@ -require "rails_helper" - -RSpec.describe Slack::Messengers::ArticleFetchedFeed, type: :service do - let!(:article) do - build(:article).tap do |article| - article.title = "Awesome article" - article.published_from_feed = true - end - end - - let(:default_params) { { article: article } } - - it "does not message slack for a new article not coming from the feed" do - sidekiq_assert_no_enqueued_jobs(only: Slack::Messengers::Worker) do - article.published_from_feed = false - - described_class.call(article: article) - end - end - - it "contains the correct info", :aggregate_failures do - sidekiq_assert_enqueued_jobs(1, only: Slack::Messengers::Worker) do - described_class.call(**default_params) - end - - job = sidekiq_enqueued_jobs(worker: Slack::Messengers::Worker).last - message = job["args"].first["message"] - - expect(message).to include(article.title) - expect(message).to include(URL.article(article)) - end - - it "messages the proper channel with the proper username and emoji", :aggregate_failures do - sidekiq_assert_enqueued_jobs(1, only: Slack::Messengers::Worker) do - described_class.call(**default_params) - end - - job = sidekiq_enqueued_jobs(worker: Slack::Messengers::Worker).last - job_args = job["args"].first - - expect(job_args["channel"]).to eq("activity") - expect(job_args["username"]).to eq("article_bot") - expect(job_args["icon_emoji"]).to eq(":robot_face:") - end -end diff --git a/spec/services/slack/workflow_webhook_spec.rb b/spec/services/slack/workflow_webhook_spec.rb new file mode 100644 index 000000000..9b827e141 --- /dev/null +++ b/spec/services/slack/workflow_webhook_spec.rb @@ -0,0 +1,24 @@ +require "rails_helper" + +RSpec.describe Slack::WorkflowWebhook, type: :service do + it "does nothing when missing SLACK_WORKFLOW_WEBHOOK_URL" do + allow(ENV).to receive(:[]).with("SLACK_WORKFLOW_WEBHOOK_URL").and_return(nil) + allow(HTTParty).to receive(:post).and_call_original + + described_class.call("test") + expect(HTTParty).not_to have_received(:post) + end + + it "send a post request to the webhook url" do + ENV["SLACK_WORKFLOW_WEBHOOK_URL"] = "https://example.com" + allow(HTTParty).to receive(:post).and_return(true) + + described_class.call("test") + expect(HTTParty).to have_received(:post).with( + "https://example.com", + body: { message: "test" }.to_json, + headers: { "Content-Type" => "application/json" }, + ) + ENV["SLACK_WORKFLOW_WEBHOOK_USERNAME"] = nil + end +end diff --git a/spec/workers/slack/workflow_webhook_worker_spec.rb b/spec/workers/slack/workflow_webhook_worker_spec.rb new file mode 100644 index 000000000..07d2edd20 --- /dev/null +++ b/spec/workers/slack/workflow_webhook_worker_spec.rb @@ -0,0 +1,21 @@ +require "rails_helper" + +RSpec.describe Slack::WorkflowWebhookWorker, type: :worker do + let(:worker) { described_class.new } + + let(:param) { "Hello World" } + + include_examples "#enqueues_on_correct_queue", "low_priority", [ + { "message" => "Hello World" }, + ] + + describe "#perform_now" do + it "sends a message to Slack" do + allow(Slack::WorkflowWebhook).to receive(:call) + + worker.perform(param) + + expect(Slack::WorkflowWebhook).to have_received(:call).with(param) + end + end +end