Adds logic

This commit is contained in:
Brusk Awat 2022-12-01 16:35:46 +03:00
parent fb26d28d9b
commit 76bca8aa8c
Signed by: broosk1993
GPG Key ID: 5D20F7E02649F74E
8 changed files with 311 additions and 17 deletions

View File

@ -1,13 +1,113 @@
require: rubocop-rails
AllCops:
TargetRubyVersion: 2.6
Style/StringLiterals:
NewCops: enable
SuggestExtensions: false
Layout/SpaceBeforeBrackets: # (new in 1.7)
Enabled: true
EnforcedStyle: double_quotes
Style/StringLiteralsInInterpolation:
Enabled: true
EnforcedStyle: double_quotes
Layout/LineLength:
Max: 120
Max: 350
Lint/AmbiguousAssignment: # (new in 1.7)
Enabled: true
Lint/DeprecatedConstants: # (new in 1.8)
Enabled: true
Lint/DuplicateBranch: # (new in 1.3)
Enabled: true
Lint/DuplicateRegexpCharacterClassElement: # (new in 1.1)
Enabled: true
Lint/EmptyBlock: # (new in 1.1)
Enabled: true
Lint/EmptyClass: # (new in 1.3)
Enabled: true
Lint/LambdaWithoutLiteralBlock: # (new in 1.8)
Enabled: true
Lint/NoReturnInBeginEndBlocks: # (new in 1.2)
Enabled: true
Lint/NumberedParameterAssignment: # (new in 1.9)
Enabled: true
Lint/OrAssignmentToConstant: # (new in 1.9)
Enabled: true
Lint/RedundantDirGlobSort: # (new in 1.8)
Enabled: true
Lint/SymbolConversion: # (new in 1.9)
Enabled: true
Lint/ToEnumArguments: # (new in 1.1)
Enabled: true
Lint/TripleQuotes: # (new in 1.9)
Enabled: true
Lint/UnexpectedBlockArity: # (new in 1.5)
Enabled: true
Lint/UnmodifiedReduceAccumulator: # (new in 1.1)
Enabled: true
Style/ArgumentsForwarding: # (new in 1.1)
Enabled: true
Style/CollectionCompact: # (new in 1.2)
Enabled: true
Style/DocumentDynamicEvalDefinition: # (new in 1.1)
Enabled: true
Style/Documentation:
Enabled: false
Style/FrozenStringLiteralComment:
Enabled: false
Style/EndlessMethod: # (new in 1.8)
Enabled: true
Style/HashConversion: # (new in 1.10)
Enabled: true
Style/HashExcept: # (new in 1.7)
Enabled: true
Style/IfWithBooleanLiteralBranches: # (new in 1.9)
Enabled: true
Style/NegatedIfElseCondition: # (new in 1.2)
Enabled: true
Style/NilLambda: # (new in 1.3)
Enabled: true
Style/RedundantArgument: # (new in 1.4)
Enabled: true
Style/SwapValues: # (new in 1.1)
Enabled: true
Rails/ActiveRecordCallbacksOrder: # (new in 2.7)
Enabled: true
Rails/AfterCommitOverride: # (new in 2.8)
Enabled: true
Rails/AttributeDefaultBlockValue: # (new in 2.9)
Enabled: true
Rails/FindById: # (new in 2.7)
Enabled: true
Rails/Inquiry: # (new in 2.7)
Enabled: true
Rails/MailerName: # (new in 2.7)
Enabled: true
Rails/MatchRoute: # (new in 2.7)
Enabled: true
Rails/NegateInclude: # (new in 2.7)
Enabled: true
Rails/Pluck: # (new in 2.7)
Enabled: true
Rails/PluckInWhere: # (new in 2.7)
Enabled: true
Rails/RenderInline: # (new in 2.7)
Enabled: true
Rails/RenderPlainText: # (new in 2.7)
Enabled: true
Rails/ShortI18n: # (new in 2.7)
Enabled: true
Rails/SquishedSQLHeredocs: # (new in 2.8)
Enabled: true
Rails/UniqueValidationWithoutIndex:
Enabled: false
Rails/WhereEquals: # (new in 2.9)
Enabled: true
Rails/WhereExists: # (new in 2.7)
Enabled: true
Rails/WhereNot: # (new in 2.8)
Enabled: true
Metrics/BlockLength:
Enabled: false
Metrics/AbcSize:
Enabled: false
Metrics/MethodLength:
Enabled: false
Metrics/CyclomaticComplexity:
Max: 15
Metrics/PerceivedComplexity:
Max: 15

81
Gemfile.lock Normal file
View File

@ -0,0 +1,81 @@
PATH
remote: .
specs:
rabbit_carrots (0.1.0)
activesupport (>= 6.0.0)
bunny (>= 2.19.0)
connection_pool (~> 2.3.0)
GEM
remote: https://rubygems.org/
specs:
activesupport (7.0.4)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
amq-protocol (2.3.2)
ast (2.4.2)
bunny (2.19.0)
amq-protocol (~> 2.3, >= 2.3.1)
sorted_set (~> 1, >= 1.0.2)
concurrent-ruby (1.1.10)
connection_pool (2.3.0)
diff-lcs (1.5.0)
i18n (1.12.0)
concurrent-ruby (~> 1.0)
json (2.6.2)
minitest (5.16.3)
parallel (1.22.1)
parser (3.1.2.1)
ast (~> 2.4.1)
rainbow (3.1.1)
rake (13.0.6)
rbtree (0.4.5)
regexp_parser (2.6.1)
rexml (3.2.5)
rspec (3.12.0)
rspec-core (~> 3.12.0)
rspec-expectations (~> 3.12.0)
rspec-mocks (~> 3.12.0)
rspec-core (3.12.0)
rspec-support (~> 3.12.0)
rspec-expectations (3.12.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-mocks (3.12.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-support (3.12.0)
rubocop (1.39.0)
json (~> 2.3)
parallel (~> 1.10)
parser (>= 3.1.2.1)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.23.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.23.0)
parser (>= 3.1.1.0)
ruby-progressbar (1.11.0)
set (1.0.3)
sorted_set (1.0.3)
rbtree
set (~> 1.0)
tzinfo (2.0.5)
concurrent-ruby (~> 1.0)
unicode-display_width (2.3.0)
PLATFORMS
x86_64-linux
DEPENDENCIES
rabbit_carrots!
rake (~> 13.0)
rspec (~> 3.0)
rubocop (~> 1.21)
BUNDLED WITH
2.3.23

View File

@ -1,6 +1,10 @@
# frozen_string_literal: true
require_relative "rabbit_carrots/version"
require 'rabbit_carrots/connection'
require 'rabbit_carrots/configuration'
require 'rabbit_carrots/railtie' if defined?(Rails)
module RabbitCarrots
class Error < StandardError; end

View File

@ -0,0 +1,14 @@
module RabbitCarrots
class << self
attr_accessor :configuration
end
def self.configure
self.configuration ||= Configuration.new
yield(configuration)
end
class Configuration
attr_accessor :rabbitmq_host, :rabbitmq_port, :rabbitmq_user, :rabbitmq_password, :rabbitmq_vhost, :routing_key_mappings, :event_bus_exchange_name
end
end

View File

@ -0,0 +1,25 @@
require 'singleton'
module RabbitCarrots
class Connection
include ::Singleton
attr_reader :connection
def initialize
@connection = Bunny.new(
host: Configuration.rabbitmq_host,
port: Configuration.rabbitmq_port,
user: Configuration.rabbitmq_user,
password: Configuration.rabbitmq_password,
vhost: Configuration.rabbitmq_vhost
)
@connection.start
end
def channel
@channel ||= ConnectionPool.new do
connection.create_channel
end
end
end
end

13
lib/railtie.rb Normal file
View File

@ -0,0 +1,13 @@
# lib/railtie.rb
require 'rabbit_carrots'
module RabbitCarrots
class Railtie < Rails::Railtie
railtie_name :rabbit_carrots
rake_tasks do
path = File.expand_path(__dir__)
Dir.glob("#{path}/tasks/**/*.rake").each { |f| load f }
end
end
end

54
lib/tasks/rmq.rake Normal file
View File

@ -0,0 +1,54 @@
require 'bunny'
namespace :rmq do
desc 'Listener for Queue'
task subscriber: :environment do
Rails.application.eager_load!
channels = RabbitCarrots::Configuration.routing_key_mappings
Rails.logger = Logger.new($stdout)
# Run RMQ Subscriber for each channel
channels.each do |channel|
handler_class = channel[:handler]
raise "#{handler_class.name} must respond to `handle!`" unless handler_class.respond_to?(:handle!)
run_task(queue_name: channel[:queue], handler_class:, routing_keys: channel[:routing_keys])
end
# Infinite loop to keep the process running
loop do
sleep 1
end
end
end
def run_task(queue_name:, handler_class:, routing_keys:)
RabbitConnection.instance.channel.with do |channel|
exchange = channel.topic(RabbitCarrots::Configuration.event_bus_exchange_name, durable: true)
Rails.logger.info "Listening on QUEUE: #{queue_name} for ROUTING KEYS: #{routing_keys}"
queue = channel.queue(queue_name, durable: true)
routing_keys.map(&:strip).each { |k| queue.bind(exchange, routing_key: k) }
queue.subscribe(block: false, manual_ack: true, prefetch: 10) do |delivery_info, properties, payload|
Rails.logger.info "Received from queue: #{queue_name}, Routing Keys: #{routing_keys}"
handler_class.handle!(channel, delivery_info, properties, payload)
channel.ack(delivery_info.delivery_tag, false)
rescue EventHandlers::Errors::NackMessage, JSON::ParserError => _e
Rails.logger.info "Nacked message: #{payload}"
channel.nack(delivery_info.delivery_tag, false, false)
rescue EventHandlers::Errors::NackAndRequeueMessage => _e
Rails.logger.info "Nacked and Requeued message: #{payload}"
channel.nack(delivery_info.delivery_tag, false, true)
rescue StandardError => e
Rails.logger.error "Error handling message: #{payload}. Error: #{e.message}"
channel.nack(delivery_info.delivery_tag, false, true)
end
Rails.logger.info 'RUN TASK ENDED'
end
end

View File

@ -8,17 +8,17 @@ Gem::Specification.new do |spec|
spec.authors = ["Brusk Awat"]
spec.email = ["broosk.edogawa@gmail.com"]
spec.summary = "TODO: Write a short summary, because RubyGems requires one."
spec.description = "TODO: Write a longer description or delete this line."
spec.homepage = "TODO: Put your gem's website or public repo URL here."
spec.summary = "A simple RabbitMQ consumer task"
spec.description = "A background task based on rake to consume RabbitMQ messages"
spec.homepage = "https://github.com/ditkrg"
spec.license = "MIT"
spec.required_ruby_version = ">= 2.6.0"
spec.required_ruby_version = ">= 3.1.0"
spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
spec.metadata["source_code_uri"] = "https://github.com/ditkrg/rabbit_carrots"
spec.metadata["changelog_uri"] = "https://github.com/ditkrg/rabbit_carrots"
# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
@ -32,7 +32,10 @@ Gem::Specification.new do |spec|
spec.require_paths = ["lib"]
# Uncomment to register a new dependency of your gem
# spec.add_dependency "example-gem", "~> 1.0"
spec.add_dependency "bunny", ">= 2.19.0"
spec.add_dependency "connection_pool", "~> 2.3.0"
spec.add_dependency "activesupport", ">= 6.0.0"
# For more information and examples about making a new gem, check out our
# guide at: https://bundler.io/guides/creating_gem.html