sqs_simplify 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SqsSimplify
4
+ class Scheduler < SqsSimplify::Base
5
+ include SqsSimplify::ExecutionHook
6
+ private_class_method :new
7
+
8
+ def initialize(message:, delay_seconds:, queue_url:, group_id: nil)
9
+ @message = message
10
+ @delay_seconds = delay_seconds
11
+ @queue_url = queue_url
12
+ @group_id = group_id
13
+ end
14
+
15
+ private
16
+
17
+ def queue_url
18
+ self.class.queue_url
19
+ end
20
+
21
+ def build_message
22
+ Message.new queue_url: @queue_url, body: dump_message(@message), delay_seconds: @delay_seconds,
23
+ group_id: @group_id
24
+ end
25
+
26
+ def send_message
27
+ sqs_message = build_message
28
+ self.class.call_hook :before_each, sqs_message
29
+ client.send_message(sqs_message.to_send).message_id
30
+ rescue Aws::SQS::Errors::NonExistentQueue => e
31
+ self.class.call_hook :resolver_exception, e, sqs_message
32
+ raise e
33
+ rescue StandardError => e
34
+ self.class.call_hook :resolver_exception, e, sqs_message
35
+ ensure
36
+ self.class.call_hook :after_each, sqs_message
37
+ end
38
+
39
+ class << self
40
+ def send_message(message:, after: nil, queue_url: nil, group_id: nil)
41
+ after = after.nil? ? 0 : after.to_i
42
+ raise 'parameter must be between 0 to 960 seconds' unless after >= 0 && after < 961
43
+
44
+ queue_url ||= self.queue_url
45
+ new(message: message, delay_seconds: after, queue_url: queue_url,
46
+ group_id: group_id).send :send_message
47
+ end
48
+
49
+ def map_queue(nickname, &block)
50
+ const_name = nickname.capitalize
51
+
52
+ class_eval <<~M, __FILE__, __LINE__ + 1
53
+ class #{const_name} < #{self}; end
54
+ private_constant '#{const_name}'
55
+
56
+ def self.#{nickname}
57
+ #{const_name}
58
+ end
59
+ M
60
+
61
+ block&.call send(nickname)
62
+ mapped_queues[nickname] = const_get(const_name).name
63
+ end
64
+
65
+ private
66
+
67
+ def mapped_queues
68
+ @mapped_queues ||= {}
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SqsSimplify
4
+ VERSION = '0.2.0'
5
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SqsSimplify
4
+ class Worker
5
+ def initialize(**options, &callback)
6
+ self.queues = options[:queues]
7
+ self.priority = options[:priority]
8
+ self.worker_size = options[:worker_size]
9
+ self.parallel_type = options[:parallel_type]
10
+ self.callback = callback
11
+ end
12
+
13
+ def perform
14
+ valid_queues!
15
+
16
+ if priority?
17
+ consumer_with_priority
18
+ else
19
+ consumer
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ attr_accessor :queues, :priority, :worker_size, :parallel_type, :callback
26
+
27
+ def sqs_consumers
28
+ @sqs_consumers ||= build_sqs_consumers
29
+ end
30
+
31
+ def build_sqs_consumers
32
+ consumers = SqsSimplify.consumers
33
+
34
+ if queues
35
+ queues.map do |queue|
36
+ consumers.find { |consumer| consumer.queue_name == queue } || Struct.new(:queue_name).new
37
+ end
38
+ else
39
+ consumers
40
+ end
41
+ end
42
+
43
+ def valid_queues!
44
+ if queues
45
+ check_option_queues!
46
+ else
47
+ check_has_any_consumer!
48
+ end
49
+ end
50
+
51
+ def check_option_queues!
52
+ all_queue_names = sqs_consumers.map(&:queue_name)
53
+
54
+ invalid_queues = queues.reject do |queue|
55
+ all_queue_names.include? queue
56
+ end
57
+
58
+ raise "Option queue invalid: [#{invalid_queues.join(', ')}]" if invalid_queues.length.positive?
59
+ end
60
+
61
+ def check_has_any_consumer!
62
+ raise 'No queue consumers were found in this project' if sqs_consumers.empty?
63
+ end
64
+
65
+ def priority?
66
+ priority
67
+ end
68
+
69
+ def consumer_with_priority
70
+ accumulated = 0
71
+ index = 0
72
+
73
+ loop do
74
+ amount = execute(sqs_consumers[index])
75
+ if amount.positive?
76
+ accumulated += amount
77
+ index = 0
78
+ else
79
+ index += 1
80
+ return accumulated if index >= queues.count
81
+ end
82
+ end
83
+ end
84
+
85
+ def consumer
86
+ number_of_executions = sqs_consumers.map do |sqs_consumer|
87
+ execute(sqs_consumer)
88
+ end
89
+ number_of_executions.reduce(&:+)
90
+ end
91
+
92
+ def execute(sqs_consumer)
93
+ options = { worker_size: worker_size, parallel_type: parallel_type }
94
+ result = sqs_consumer.consume_messages(**options)
95
+ callback&.call(result, sqs_consumer)
96
+ result
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aws-sdk-sqs'
4
+ require 'fileutils'
5
+ require 'json'
6
+ require 'logger'
7
+ require 'ostruct'
8
+ require 'parallel'
9
+ require 'pathname'
10
+ require 'timeout'
11
+
12
+ require 'sqs_simplify/execution_hook'
13
+ require 'sqs_simplify/client'
14
+ require 'sqs_simplify/base'
15
+
16
+ require 'sqs_simplify/command'
17
+ require 'sqs_simplify/consumer'
18
+ require 'sqs_simplify/faker_client'
19
+
20
+ require 'sqs_simplify/message'
21
+ require 'sqs_simplify/scheduler'
22
+ require 'sqs_simplify/version'
23
+
24
+ require 'sqs_simplify/worker'
25
+ require 'sqs_simplify/job'
26
+ require 'sqs_simplify/dead_queue'
27
+
28
+ require 'sqs_simplify/errors/execution_expired'
29
+ require 'sqs_simplify/errors/non_existent_queue'
30
+ require 'sqs_simplify/errors/reserved_method_name'
31
+
32
+ module SqsSimplify
33
+ include SqsSimplify::ExecutionHook
34
+
35
+ add_hook :message_not_deleted, :after_fork
36
+
37
+ class << self
38
+ def configure
39
+ block_given? ? yield(settings) : settings
40
+ end
41
+
42
+ def settings
43
+ @settings ||= OpenStruct.new(
44
+ hooks: self,
45
+ worker: self::Worker,
46
+ root: Pathname.new(Dir.pwd)
47
+ )
48
+ end
49
+
50
+ def consumers
51
+ @consumers ||= []
52
+ end
53
+
54
+ def schedulers
55
+ @schedulers ||= []
56
+ end
57
+
58
+ def logger
59
+ return @logger if @logger
60
+
61
+ path = settings.log_dir || "#{settings.root}/log"
62
+ FileUtils.mkdir_p(path) unless File.directory?(path)
63
+ @logger = Logger.new("#{path}/sqs_simplify.log")
64
+ end
65
+ end
66
+
67
+ class Error < StandardError; end
68
+ end
data/rubocop.yml ADDED
@@ -0,0 +1,3 @@
1
+ Lint/MissingSuper:
2
+ Exclude:
3
+ - 'app/services/**/*'
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/sqs_simplify/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'sqs_simplify'
7
+ spec.version = SqsSimplify::VERSION
8
+ spec.authors = ['Ralph Baesso', 'Nathan Meira', 'Joathan Fontan']
9
+ spec.email = ['ralphsbaesso@gmail.com', 'nathanmeira1@gmail.com', 'joathan.fontan@brobotbr.com.br']
10
+
11
+ spec.summary = 'Simple producers, consumers and jobs on top of Amazon SQS'
12
+ spec.description = 'Send, consume and schedule Amazon SQS messages with jobs, consumers, ' \
13
+ 'dead letter queues, FIFO group ids and a worker command.'
14
+ spec.homepage = 'https://github.com/joathan-fontan/sqs_simplify'
15
+ spec.license = 'MIT'
16
+ spec.required_ruby_version = Gem::Requirement.new('>= 3.0.0')
17
+
18
+ spec.metadata['homepage_uri'] = spec.homepage
19
+ spec.metadata['source_code_uri'] = spec.homepage
20
+ spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/main/CHANGELOG.md"
21
+ spec.metadata['rubygems_mfa_required'] = 'true'
22
+
23
+ # Specify which files should be added to the gem when it is released.
24
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
26
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
27
+ end
28
+ spec.bindir = 'exe'
29
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ['lib']
31
+
32
+ spec.add_runtime_dependency 'aws-sdk-sqs', '~> 1.0'
33
+ spec.add_runtime_dependency 'parallel', '>= 1.20', '< 3'
34
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sqs_simplify
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Ralph Baesso
8
+ - Nathan Meira
9
+ - Joathan Fontan
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 1980-01-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: aws-sdk-sqs
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: parallel
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '1.20'
35
+ - - "<"
36
+ - !ruby/object:Gem::Version
37
+ version: '3'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: '1.20'
45
+ - - "<"
46
+ - !ruby/object:Gem::Version
47
+ version: '3'
48
+ description: Send, consume and schedule Amazon SQS messages with jobs, consumers,
49
+ dead letter queues, FIFO group ids and a worker command.
50
+ email:
51
+ - ralphsbaesso@gmail.com
52
+ - nathanmeira1@gmail.com
53
+ - joathan.fontan@brobotbr.com.br
54
+ executables: []
55
+ extensions: []
56
+ extra_rdoc_files: []
57
+ files:
58
+ - ".gitignore"
59
+ - ".rspec"
60
+ - ".travis.yml"
61
+ - CHANGELOG.md
62
+ - Gemfile
63
+ - LICENSE.txt
64
+ - README.md
65
+ - README.pt-br.md
66
+ - Rakefile
67
+ - bin/console
68
+ - bin/setup
69
+ - lib/sqs_simplify.rb
70
+ - lib/sqs_simplify/base.rb
71
+ - lib/sqs_simplify/client.rb
72
+ - lib/sqs_simplify/command.rb
73
+ - lib/sqs_simplify/consumer.rb
74
+ - lib/sqs_simplify/dead_queue.rb
75
+ - lib/sqs_simplify/errors/execution_expired.rb
76
+ - lib/sqs_simplify/errors/non_existent_queue.rb
77
+ - lib/sqs_simplify/errors/reserved_method_name.rb
78
+ - lib/sqs_simplify/execution_hook.rb
79
+ - lib/sqs_simplify/faker_client.rb
80
+ - lib/sqs_simplify/job.rb
81
+ - lib/sqs_simplify/message.rb
82
+ - lib/sqs_simplify/scheduler.rb
83
+ - lib/sqs_simplify/version.rb
84
+ - lib/sqs_simplify/worker.rb
85
+ - rubocop.yml
86
+ - sqs_simplify.gemspec
87
+ homepage: https://github.com/joathan-fontan/sqs_simplify
88
+ licenses:
89
+ - MIT
90
+ metadata:
91
+ homepage_uri: https://github.com/joathan-fontan/sqs_simplify
92
+ source_code_uri: https://github.com/joathan-fontan/sqs_simplify
93
+ changelog_uri: https://github.com/joathan-fontan/sqs_simplify/blob/main/CHANGELOG.md
94
+ rubygems_mfa_required: 'true'
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 3.0.0
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubygems_version: 4.0.15
110
+ specification_version: 4
111
+ summary: Simple producers, consumers and jobs on top of Amazon SQS
112
+ test_files: []