From c209c96322a6ce15ec7a4cb6ea9518c1974fdf58 Mon Sep 17 00:00:00 2001 From: dmitrytrager Date: Mon, 10 Nov 2025 23:41:45 +0100 Subject: [PATCH] Add builder, job and generator for json data with provider regions #444 --- app/jobs/provider_region_data_job.rb | 31 ++++++++++++++ app/services/json_generator/base.rb | 5 +++ .../json_generator/provider_regions.rb | 20 +++++++++ app/services/provider_region_data_builder.rb | 5 +++ config/recurring.yml | 4 ++ spec/jobs/provider_region_data_job_spec.rb | 21 ++++++++++ .../json_generator/provider_regions_spec.rb | 42 +++++++++++++++++++ spec/services/text_generator/tags_spec.rb | 2 +- 8 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 app/jobs/provider_region_data_job.rb create mode 100644 app/services/json_generator/base.rb create mode 100644 app/services/json_generator/provider_regions.rb create mode 100644 app/services/provider_region_data_builder.rb create mode 100644 spec/jobs/provider_region_data_job_spec.rb create mode 100644 spec/services/json_generator/provider_regions_spec.rb diff --git a/app/jobs/provider_region_data_job.rb b/app/jobs/provider_region_data_job.rb new file mode 100644 index 00000000..998dccae --- /dev/null +++ b/app/jobs/provider_region_data_job.rb @@ -0,0 +1,31 @@ +class ProviderRegionDataJob < ApplicationJob + limits_concurrency to: 1, key: ->(language_id) { "hard-limit" } + + def perform(language_id) + language = Language.find(language_id) + deliver_provider_region_data(language) + end + + private + + def deliver_provider_region_data(language) + provider_region_data(language).tap { |file| deliver(file) } + end + + def provider_region_data(language) + FileToUpload.new( + content: JsonGenerator::ProviderRegions.new(language).perform, + name: "#{language.file_storage_prefix}provider_region_data.json", + path: "#{language.file_storage_prefix}CMES-v2", + ) + end + + def deliver(file) + FileWorker.new( + share: ENV["AZURE_STORAGE_SHARE_NAME"], + name: file.name, + path: file.path, + file: file.content, + ).send + end +end diff --git a/app/services/json_generator/base.rb b/app/services/json_generator/base.rb new file mode 100644 index 00000000..cedd4820 --- /dev/null +++ b/app/services/json_generator/base.rb @@ -0,0 +1,5 @@ +class JsonGenerator::Base + def perform + json_content + end +end diff --git a/app/services/json_generator/provider_regions.rb b/app/services/json_generator/provider_regions.rb new file mode 100644 index 00000000..5136a5e7 --- /dev/null +++ b/app/services/json_generator/provider_regions.rb @@ -0,0 +1,20 @@ +class JsonGenerator::ProviderRegions < JsonGenerator::Base + def initialize(language, **args) + @language = language + @args = args + end + + private + + attr_reader :language, :args + + def json_content + scope + .map { |provider| { name: provider.name, prefix: provider.file_name_prefix, regions: provider.regions } } + .to_json + end + + def scope + language.providers.includes(:regions) + end +end diff --git a/app/services/provider_region_data_builder.rb b/app/services/provider_region_data_builder.rb new file mode 100644 index 00000000..9b8bdbdd --- /dev/null +++ b/app/services/provider_region_data_builder.rb @@ -0,0 +1,5 @@ +class ProviderRegionDataBuilder + def perform + ProviderRegionDataJob.perform_later + end +end diff --git a/config/recurring.yml b/config/recurring.yml index 895a9a63..53cf6761 100644 --- a/config/recurring.yml +++ b/config/recurring.yml @@ -4,6 +4,10 @@ default: &default command: LanguageFilesScheduler.new.perform queue: default schedule: "@hourly" + provider_region_data: + command: ProviderRegionDataBuilder.new.perform + queue: default + schedule: "@daily" clear_solid_queue_finished_jobs: command: "SolidQueue::Job.clear_finished_in_batches(sleep_between_batches: 0.3)" schedule: every hour at minute 12 diff --git a/spec/jobs/provider_region_data_job_spec.rb b/spec/jobs/provider_region_data_job_spec.rb new file mode 100644 index 00000000..023ebd32 --- /dev/null +++ b/spec/jobs/provider_region_data_job_spec.rb @@ -0,0 +1,21 @@ +require "rails_helper" + +RSpec.describe ProviderRegionDataJob, type: :job do + let(:language) { create(:language) } + + describe "#perform" do + it "generates provider region data" do + generator = instance_double(JsonGenerator::ProviderRegions) + allow(JsonGenerator::ProviderRegions).to receive(:new).with(language).and_return(generator) + expect(generator).to receive(:perform) + + described_class.perform_now(language.id) + end + + context "when language does not exist" do + it "raises an error" do + expect { described_class.perform_now(-1) }.to raise_error(ActiveRecord::RecordNotFound) + end + end + end +end diff --git a/spec/services/json_generator/provider_regions_spec.rb b/spec/services/json_generator/provider_regions_spec.rb new file mode 100644 index 00000000..ae250e8e --- /dev/null +++ b/spec/services/json_generator/provider_regions_spec.rb @@ -0,0 +1,42 @@ +require "rails_helper" + +RSpec.describe JsonGenerator::ProviderRegions do + subject { described_class.new(language) } + + let(:language) { create(:language) } + + it "generates empty json" do + expect(subject.perform).to eq("[]") + end + + context "when providers exist" do + let!(:provider) { create(:provider) } + + before do + create(:topic, provider:, language:) + end + + it "generates json with provider data" do + expect(subject.perform).to eq([ + { + name: provider.name, + prefix: provider.file_name_prefix, + regions: provider.regions, + }, + ].to_json) + end + end + + context "when provider does not belong to language" do + let(:other_language) { create(:language) } + let!(:provider) { create(:provider) } + + before do + create(:topic, provider:, language: other_language) + end + + it "generates empty json" do + expect(subject.perform).to eq("[]") + end + end +end diff --git a/spec/services/text_generator/tags_spec.rb b/spec/services/text_generator/tags_spec.rb index 45abc7be..3dba9c95 100644 --- a/spec/services/text_generator/tags_spec.rb +++ b/spec/services/text_generator/tags_spec.rb @@ -15,7 +15,7 @@ before do tag_names = [ "cold", "flu", "cough" ] tag_names.each do |tag_name| - tag = create(:tag, name: tag_name) + create(:tag, name: tag_name) end topic.tag_list.add(tag_names) topic.save