diff --git a/check-manager/.tool-versions b/check-manager/.tool-versions new file mode 100644 index 0000000..5aa8e0c --- /dev/null +++ b/check-manager/.tool-versions @@ -0,0 +1 @@ +ruby 3.3.6 diff --git a/check-manager/app/contexts/checks/create_service.rb b/check-manager/app/contexts/checks/create_service.rb new file mode 100644 index 0000000..493a3ce --- /dev/null +++ b/check-manager/app/contexts/checks/create_service.rb @@ -0,0 +1,14 @@ +class Checks::CreateService + include Callable + extend Dry::Initializer + + param :message + + def call + attachment_id = message.dig(:payload, :attachment_id) + + raise Error, 'Attachment id can not be blank' + + Check.find_or_create_by(attachment_id: attachment_id) + end +end diff --git a/check-manager/app/contexts/checks/save_message_service.rb b/check-manager/app/contexts/checks/save_message_service.rb new file mode 100644 index 0000000..f3b32bc --- /dev/null +++ b/check-manager/app/contexts/checks/save_message_service.rb @@ -0,0 +1,15 @@ +class Checks::SaveMessageService + include Callable + extend Dry::Initializer + + param :attachment_id + param :message + + def call + check = Check.find_or_create_by(attachment_id: attachment_id) + check.with_lock do + check.messages << message + check.save + end + end +end diff --git a/check-manager/app/contexts/checks/tesseract_service.rb b/check-manager/app/contexts/checks/tesseract_service.rb new file mode 100644 index 0000000..fe5054b --- /dev/null +++ b/check-manager/app/contexts/checks/tesseract_service.rb @@ -0,0 +1,59 @@ +class Checks::TesseractService + include Callable + extend Dry::Initializer + + param :message + + def call + file_path = message.dig(:payload, :file_path) + file = download_file(file_path) + response = send_to_tesseract(file) + + raise Error, 'Tesseract problem' unless response.is_a?(Net::HTTPSuccess) + + Checks::SaveMessageService.call(message.dig(:payload, :attachment_id), response.body) + end + + private + + + def service + + end + + def download_file(url) + uri = URI.parse(url) + + Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http| + request = Net::HTTP::Get.new(uri) + + http.request(request) do |response| + raise Error, "Failed to download file: #{response.code} #{response.message}" unless response.is_a?(Net::HTTPSuccess) + + temp_file = Tempfile.new(["downloaded_file_#{Time.current.to_i}", File.extname(uri.path)]) + temp_file.binmode + + response.read_body do |chunk| + temp_file.write(chunk) + end + + temp_file.close + return temp_file + end + end + end + + def send_to_tesseract(file) + uri = URI.parse(ENV['TESSERACT_URL']) + + file_content = File.binread(file.path) + + request = Net::HTTP::Post.new(uri) + request['Content-Type'] = 'application/x-www-form-urlencoded' + request.body = file_content + + Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http| + http.request(request) + end + end +end diff --git a/check-manager/app/contexts/pays/analyse_service.rb b/check-manager/app/contexts/pays/analyse_service.rb index 9d1a9f1..0b3adea 100644 --- a/check-manager/app/contexts/pays/analyse_service.rb +++ b/check-manager/app/contexts/pays/analyse_service.rb @@ -5,10 +5,22 @@ class Pays::AnalyseService param :message def call + return unless available_send? next_message = Pays::BuildMessageService.call( message: message, + check_messages: check.messages, routing_key: 'pay_analyse') RabbitMessages::Send.call(next_message) end + + private + + def available_send? + check&.messages&.size >= ENV['MESSAGES_SIZE'] + end + + def check + @check ||= Check.find_by(attachment_id: message.dig(:payload, :attachment_id)) + end end diff --git a/check-manager/app/contexts/pays/build_message_service.rb b/check-manager/app/contexts/pays/build_message_service.rb index bd3ef50..cc0963a 100644 --- a/check-manager/app/contexts/pays/build_message_service.rb +++ b/check-manager/app/contexts/pays/build_message_service.rb @@ -4,6 +4,7 @@ class Pays::BuildMessageService option :message option :routing_key + option :check_messages def call { @@ -13,7 +14,7 @@ def call full_path: message.dig(:payload, :full_path), attachment_id: message.dig(:payload, :attachment_id), created_at: message.dig(:payload, :created_at), - message: message.dig(:payload, :message) + message: check_messages }, created_at: Time.now.utc.to_i, routing_key: routing_key diff --git a/check-manager/app/contexts/pays/save_message_service.rb b/check-manager/app/contexts/pays/save_message_service.rb new file mode 100644 index 0000000..da76a81 --- /dev/null +++ b/check-manager/app/contexts/pays/save_message_service.rb @@ -0,0 +1,14 @@ +class Pays::SaveMessageService + include Callable + extend Dry::Initializer + + param :message + + def call + attachment_id = message.dig(:payload, :attachment_id) + + raise Error, 'Attachment id can not be blank' + + Checks::SaveMessageService.call(attachment_id, message.dig(:payload, :message)) + end +end diff --git a/check-manager/app/models/check.rb b/check-manager/app/models/check.rb new file mode 100644 index 0000000..2c10d25 --- /dev/null +++ b/check-manager/app/models/check.rb @@ -0,0 +1,2 @@ +class Check < ApplicationRecord +end diff --git a/check-manager/app/workers/inbox_listener.rb b/check-manager/app/workers/inbox_listener.rb index 3ab3565..5c6fa9e 100644 --- a/check-manager/app/workers/inbox_listener.rb +++ b/check-manager/app/workers/inbox_listener.rb @@ -3,7 +3,7 @@ class InboxListener include RabbitMessages::Logging ACTION_HANDLERS = { - attachment_registered: Checks::RecognizeService + attachment_registered: [Checks::CreateService, Checks::TesseractService, Checks::RecognizeService] }.freeze QUEUE_NAME = Settings.sneakers.inbox_queue PG_EXCEPTION = [ @@ -42,10 +42,10 @@ def process_message parsed_message, RabbitMessage::INCOME_MESSAGE, action) - handler = ACTION_HANDLERS[action&.to_sym] - raise Error, "Action #{action} is not supported" unless handler + handlers = ACTION_HANDLERS[action&.to_sym] + raise Error, "Action #{action} is not supported" unless handlers - handler.call(parsed_message) + handlers.each { |handler| handler.call(message) } rabbit_message.update!(success: true) end diff --git a/check-manager/app/workers/recognizer_listener.rb b/check-manager/app/workers/recognizer_listener.rb index d87ef45..bea875f 100644 --- a/check-manager/app/workers/recognizer_listener.rb +++ b/check-manager/app/workers/recognizer_listener.rb @@ -3,7 +3,7 @@ class RecognizerListener include RabbitMessages::Logging ACTION_HANDLERS = { - recognized_result: Pays::AnalyseService + recognized_result: [Pays::SaveMessageService, Pays::AnalyseService] }.freeze QUEUE_NAME = Settings.sneakers.recognizer_queue PG_EXCEPTION = [ diff --git a/check-manager/db/migrate/20251118181614_create_checks.rb b/check-manager/db/migrate/20251118181614_create_checks.rb new file mode 100644 index 0000000..826accb --- /dev/null +++ b/check-manager/db/migrate/20251118181614_create_checks.rb @@ -0,0 +1,10 @@ +class CreateChecks < ActiveRecord::Migration[8.0] + def change + create_table :checks do |t| + t.text :messages, array: true, default: [] + t.bigint :attachment_id, index: true + + t.timestamps + end + end +end diff --git a/check-manager/db/schema.rb b/check-manager/db/schema.rb index ab1de8d..2defb0d 100644 --- a/check-manager/db/schema.rb +++ b/check-manager/db/schema.rb @@ -10,11 +10,19 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.0].define(version: 2025_03_01_085819) do +ActiveRecord::Schema[8.0].define(version: 2025_11_18_181614) do # These are extensions that must be enabled in order to support this database enable_extension "pg_catalog.plpgsql" enable_extension "pgcrypto" + create_table "checks", force: :cascade do |t| + t.text "messages", default: [], array: true + t.bigint "attachment_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["attachment_id"], name: "index_checks_on_attachment_id" + end + create_table "rabbit_messages", id: :uuid, default: -> { "gen_random_uuid()" }, comment: "Логгирование RabbitMQ-сообщений", force: :cascade do |t| t.string "action", null: false, comment: "Тип/экшен сообщения" t.jsonb "data", comment: "Структура сообщения, которая будет передаваться следующему микросервису" diff --git a/check-manager/spec/factories/checks.rb b/check-manager/spec/factories/checks.rb new file mode 100644 index 0000000..09310bd --- /dev/null +++ b/check-manager/spec/factories/checks.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :check do + + end +end diff --git a/check-manager/spec/models/check_spec.rb b/check-manager/spec/models/check_spec.rb new file mode 100644 index 0000000..0429ef6 --- /dev/null +++ b/check-manager/spec/models/check_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Check, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end