fourkites-sqspoller-v2 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +4 -0
- data/LICENSE +340 -0
- data/README.md +72 -0
- data/Rakefile +1 -0
- data/bin/run_sqs_poller +5 -0
- data/bin/sqs_poller.service +13 -0
- data/bin/sqs_poller_v2 +18 -0
- data/images/SQS_Poller_V2.png +0 -0
- data/install.sh +10 -0
- data/lib/config/newrelic.yml +71 -0
- data/lib/seahorse/stringio.rb +10 -0
- data/lib/sqs-ruby-example-consume-queue.rb +16 -0
- data/lib/sqs-ruby-example-create-queue.rb +107 -0
- data/lib/sqspoller/common/ring_buffer.rb +74 -0
- data/lib/sqspoller/common/utils.rb +47 -0
- data/lib/sqspoller/logger/logger.rb +40 -0
- data/lib/sqspoller/metrics/log_reporter.rb +19 -0
- data/lib/sqspoller/metrics/queue_stats_reporter.rb +42 -0
- data/lib/sqspoller/metrics/sqs_poller_metrics.rb +109 -0
- data/lib/sqspoller/poll/queue_controller.rb +141 -0
- data/lib/sqspoller/poll/queue_poller.rb +73 -0
- data/lib/sqspoller/process/message_handler.rb +53 -0
- data/lib/sqspoller/process/task_finalizer.rb +88 -0
- data/lib/sqspoller/process/task_worker.rb +50 -0
- data/lib/sqspoller/process/worker_controller.rb +81 -0
- data/lib/sqspoller/sqs_poller.rb +147 -0
- data/lib/sqspoller/version.rb +3 -0
- data/lib/sqspoller/worker_task.rb +17 -0
- data/lib/sqspoller.rb +7 -0
- data/lib/test.yaml +15 -0
- data/sqspoller.gemspec +30 -0
- metadata +180 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
require "concurrent"
|
2
|
+
require "net/http"
|
3
|
+
require "rest-client"
|
4
|
+
require "json"
|
5
|
+
require "sqspoller/logger/logger"
|
6
|
+
|
7
|
+
# This handles the SQS message and forward to local puma server and get the response.
|
8
|
+
module SqsPoller
|
9
|
+
module Process
|
10
|
+
class MessageHandler
|
11
|
+
|
12
|
+
HEADERS = {
|
13
|
+
'Content-Type' => 'application/json',
|
14
|
+
'Accept' => 'application/json'
|
15
|
+
}
|
16
|
+
|
17
|
+
def initialize(worker_configuration)
|
18
|
+
@logger = SqsPoller::Logger.get_new_logger(self.class.name)
|
19
|
+
@http_method = worker_configuration[:http_method]
|
20
|
+
@http_url = worker_configuration[:http_url]
|
21
|
+
@timeout = worker_configuration[:timeout] ? worker_configuration[:timeout].to_i : 450
|
22
|
+
@uri = URI(@http_url)
|
23
|
+
end
|
24
|
+
|
25
|
+
def handle(message, message_id)
|
26
|
+
parsed_message = JSON.parse(message)
|
27
|
+
# @logger.info parsed_message
|
28
|
+
if @http_method.downcase == "post"
|
29
|
+
RestClient::Request.execute(:method => :post, :url => @http_url, :payload => parsed_message.to_json, :headers => HEADERS, :timeout => @timeout, :open_timeout => 5) do |response, request, result|
|
30
|
+
process_http_response response
|
31
|
+
end
|
32
|
+
elsif @http_method.downcase == "get"
|
33
|
+
RestClient::Request.execute(:method => :get, :url => @http_url, :payload => parsed_message.to_json, :headers => HEADERS, :timeout => @timeout, :open_timeout => 5) do |response, request, result|
|
34
|
+
process_http_response response
|
35
|
+
end
|
36
|
+
else
|
37
|
+
raise "Invalid http_method provided. #{http_method}"
|
38
|
+
end
|
39
|
+
parsed_message["MessageType"]
|
40
|
+
end
|
41
|
+
|
42
|
+
def process_http_response(response)
|
43
|
+
case response.code
|
44
|
+
when 200
|
45
|
+
return "OK"
|
46
|
+
else
|
47
|
+
raise "Service did not return 200 OK response. #{response.code}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require "logger"
|
2
|
+
require "concurrent"
|
3
|
+
require "net/http"
|
4
|
+
require "rest-client"
|
5
|
+
require "json"
|
6
|
+
require "sqspoller/logger/logger"
|
7
|
+
require "sqspoller/common/ring_buffer"
|
8
|
+
require "sqspoller/poll/queue_controller"
|
9
|
+
|
10
|
+
# TaskFinalizer will delete the batch of messages from SQS.
|
11
|
+
# It used the RingBuffer as the cache (Not persisted. We will lose all the messages if process killed or stopped.) to hold all completed tasks.
|
12
|
+
# When buffer filled the half the sizes it will try to delete the messages using sqs batch delete (max 10 per batch) from SQS and with max of 5 retries
|
13
|
+
module SqsPoller
|
14
|
+
module Process
|
15
|
+
class TaskFinalizer
|
16
|
+
|
17
|
+
DEFAULT_FINALIZE_TIMER_DELAY = 5.0
|
18
|
+
MAX_SQS_DELETE_BATCH_SIZE = 10
|
19
|
+
MAX_DELETE_RETRY = 5
|
20
|
+
|
21
|
+
def initialize(buffer_size)
|
22
|
+
@logger = SqsPoller::Logger.get_new_logger(self.class.name)
|
23
|
+
@buffer_size = buffer_size
|
24
|
+
@completed_tasks = SqsPoller::Common::RingBuffer.new(buffer_size * 2)
|
25
|
+
schedule_timer
|
26
|
+
end
|
27
|
+
|
28
|
+
def buffer_size
|
29
|
+
@buffer_size
|
30
|
+
end
|
31
|
+
|
32
|
+
def finalize(completed_task)
|
33
|
+
@completed_tasks.push completed_task
|
34
|
+
if @completed_tasks.count >= @buffer_size
|
35
|
+
@timer.reset
|
36
|
+
finalize_tasks
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def schedule_timer
|
43
|
+
@timer = Concurrent::ScheduledTask.new(DEFAULT_FINALIZE_TIMER_DELAY) {
|
44
|
+
finalize_tasks true
|
45
|
+
schedule_timer
|
46
|
+
}
|
47
|
+
@timer.execute
|
48
|
+
end
|
49
|
+
|
50
|
+
def finalize_tasks(scheduled = false)
|
51
|
+
return if !scheduled && @completed_tasks.count < @buffer_size
|
52
|
+
completed_tasks = @completed_tasks.flush
|
53
|
+
begin
|
54
|
+
task_group = completed_tasks.group_by { |task|
|
55
|
+
task[:queue_name]
|
56
|
+
}
|
57
|
+
task_group.each { |queue, tasks|
|
58
|
+
messages = tasks.map { |task|
|
59
|
+
task[:message]
|
60
|
+
}
|
61
|
+
messages.each_slice(MAX_SQS_DELETE_BATCH_SIZE) do |msgs|
|
62
|
+
SqsPoller::Poller::QueueController.delete_messages(queue, msgs)
|
63
|
+
end
|
64
|
+
@logger.debug "Deleted #{messages.size} messages from #{queue}"
|
65
|
+
}
|
66
|
+
rescue Exception => e
|
67
|
+
@logger.error "TaskFinalizer Caught error: #{e.message}, #{e.backtrace.join("\n")}"
|
68
|
+
finalize_task_individually(completed_tasks)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def finalize_task_individually(completed_tasks)
|
73
|
+
completed_tasks.each { |task|
|
74
|
+
begin
|
75
|
+
SqsPoller::Poller::QueueController.delete_message(task[:queue_name], task[:message])
|
76
|
+
rescue Exception => e
|
77
|
+
retry_delete = task[:retry_delete].present? ? task[:retry_delete] : 0
|
78
|
+
if retry_delete < MAX_DELETE_RETRY
|
79
|
+
task[:delete_retry] = retry_delete + 1
|
80
|
+
@completed_tasks.push task
|
81
|
+
end
|
82
|
+
end
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "logger"
|
2
|
+
require "concurrent"
|
3
|
+
require "net/http"
|
4
|
+
require "sqspoller/worker_task"
|
5
|
+
require "sqspoller/common/ring_buffer"
|
6
|
+
require "sqspoller/process/task_finalizer"
|
7
|
+
require "sqspoller/common/utils"
|
8
|
+
require "sqspoller/metrics/sqs_poller_metrics"
|
9
|
+
|
10
|
+
# This Worker keep polls the task queue (SizedQueue with blocking) and delegate the message the message handler.
|
11
|
+
# Once message is process based on its status will send to task finalizer if the message is successfully handled.
|
12
|
+
# else it will ignore the message. Based on message visibility timeout in SQS it will reappear and processed.
|
13
|
+
module SqsPoller
|
14
|
+
module Process
|
15
|
+
class Worker
|
16
|
+
|
17
|
+
def initialize(worker_name, task_queue, task_finalizer, message_handler)
|
18
|
+
@worker_name = worker_name
|
19
|
+
@task_queue = task_queue
|
20
|
+
@message_handler = message_handler
|
21
|
+
@task_finalizer = task_finalizer
|
22
|
+
@logger = SqsPoller::Logger.get_new_logger("#{self.class.name}-#{@worker_name}")
|
23
|
+
end
|
24
|
+
|
25
|
+
def run
|
26
|
+
loop do
|
27
|
+
task = @task_queue.pop
|
28
|
+
message = task[:message]
|
29
|
+
success = false
|
30
|
+
timer = SqsPoller::Common::Utils.start_timer
|
31
|
+
message_type= "UNKNOWN"
|
32
|
+
begin
|
33
|
+
@logger.debug "Starting worker task for message: #{message.message_id}"
|
34
|
+
message_type = @message_handler.handle(message.body, message.message_id)
|
35
|
+
@logger.debug "Finished worker task for message: #{message.message_id}"
|
36
|
+
success = true
|
37
|
+
rescue Exception => e
|
38
|
+
@logger.error "Caught error: #{e.message}, #{e.backtrace.join("\n")} for message id: #{message.message_id}, body: #{message.body}"
|
39
|
+
end
|
40
|
+
elapsed_time = timer.stop
|
41
|
+
queue_wait_time = timer.start_time - task[:queue_time]
|
42
|
+
@logger.info "Task Completed queue_name: #{task[:queue_name]}, message_id: #{message.message_id}, message_type: #{message_type}, elapsed_time: #{elapsed_time}, queue_wait_time: #{queue_wait_time} message_count: #{task[:index]}"
|
43
|
+
SqsPoller::Metrics.record(task, success, timer, elapsed_time)
|
44
|
+
@task_finalizer.finalize(task) if success
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require "logger"
|
2
|
+
require "concurrent"
|
3
|
+
require "net/http"
|
4
|
+
require "sqspoller/worker_task"
|
5
|
+
require "sqspoller/common/ring_buffer"
|
6
|
+
require "sqspoller/process/task_finalizer"
|
7
|
+
require "sqspoller/common/utils"
|
8
|
+
require "sqspoller/metrics/sqs_poller_metrics"
|
9
|
+
require "sqspoller/process/task_worker"
|
10
|
+
|
11
|
+
# This manages all process task workers threads using threadpools.
|
12
|
+
# The number of thread can be configured in yaml config using concurrency:
|
13
|
+
# Refer test.yaml
|
14
|
+
module SqsPoller
|
15
|
+
module Process
|
16
|
+
class WorkerController
|
17
|
+
|
18
|
+
private_class_method :new
|
19
|
+
|
20
|
+
def initialize(worker_count, task_queue, worker_task, auto_tuning = true)
|
21
|
+
@task_queue = task_queue
|
22
|
+
@message_handler = worker_task
|
23
|
+
@dynamic_scheduling = auto_tuning
|
24
|
+
@worker_count = worker_count
|
25
|
+
@task_workers = Concurrent::RubyThreadPoolExecutor.new(min_threads: @worker_count)
|
26
|
+
@task_finalizer = TaskFinalizer.new(task_queue.max)
|
27
|
+
@logger = SqsPoller::Logger.get_new_logger(self.class.name)
|
28
|
+
@started = false
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.get
|
32
|
+
return @instance if @instance
|
33
|
+
raise "WorkerController not yet started"
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.start (worker_count, task_queue, worker_task, auto_tuning = true)
|
37
|
+
return @instance if @instance
|
38
|
+
@instance = new(worker_count, task_queue, worker_task, auto_tuning)
|
39
|
+
@instance.start
|
40
|
+
@instance
|
41
|
+
end
|
42
|
+
|
43
|
+
def started?
|
44
|
+
@started
|
45
|
+
end
|
46
|
+
|
47
|
+
def start
|
48
|
+
@logger.info "Starting #{@worker_count} workers"
|
49
|
+
begin
|
50
|
+
start_workers
|
51
|
+
@started = true
|
52
|
+
rescue Exception => e
|
53
|
+
@logger.error "Task Worker killed for and restarted. Caught error: #{e.message}, #{e.backtrace.join("\n")}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def shutdown
|
58
|
+
@logger.info "WorkerController Terminated"
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def start_workers
|
64
|
+
@worker_count.times do |index|
|
65
|
+
@task_workers.post do
|
66
|
+
@logger.info "Starting worker #{index}"
|
67
|
+
worker = Worker.new("Worker-#{index}", @task_queue, @task_finalizer, @message_handler)
|
68
|
+
loop do
|
69
|
+
begin
|
70
|
+
worker.run
|
71
|
+
rescue Exception => e
|
72
|
+
@logger.error "Task Worker killed for and restarted. Caught error: #{e.message}, #{e.backtrace.join("\n")}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require "logger"
|
2
|
+
require "concurrent"
|
3
|
+
require "net/http"
|
4
|
+
require "yaml"
|
5
|
+
require "erb"
|
6
|
+
require "sqspoller"
|
7
|
+
require "sqspoller/worker_task"
|
8
|
+
require "sqspoller/poll/queue_controller"
|
9
|
+
require "sqspoller/process/worker_controller"
|
10
|
+
require "sqspoller/process/task_finalizer"
|
11
|
+
require "sqspoller/process/message_handler"
|
12
|
+
require 'new_relic/agent'
|
13
|
+
|
14
|
+
# This is the starting point of SQS polling. Load the Yaml config and starts QueueController and WorkerController.
|
15
|
+
# Waits until process get kill or stop.
|
16
|
+
module SqsPoller
|
17
|
+
class << self
|
18
|
+
|
19
|
+
def sym(map)
|
20
|
+
if map.class == Hash
|
21
|
+
map = map.inject({}) { |memo, (k, v)| memo[k.to_sym] = sym(v); memo }
|
22
|
+
end
|
23
|
+
map
|
24
|
+
end
|
25
|
+
|
26
|
+
def daemonize(filename)
|
27
|
+
raise 'Must run as root' if Process.euid != 0
|
28
|
+
|
29
|
+
raise 'First fork failed' if (pid = fork) == -1
|
30
|
+
exit unless pid.nil?
|
31
|
+
|
32
|
+
Process.setsid
|
33
|
+
raise 'Second fork failed' if (pid = fork) == -1
|
34
|
+
exit unless pid.nil?
|
35
|
+
puts "Daemon pid: #{Process.pid}" # Or save it somewhere, etc.
|
36
|
+
|
37
|
+
Dir.chdir '/'
|
38
|
+
File.umask 0000
|
39
|
+
|
40
|
+
STDIN.reopen filename
|
41
|
+
STDOUT.reopen '/dev/null', 'a'
|
42
|
+
STDERR.reopen STDOUT
|
43
|
+
end
|
44
|
+
|
45
|
+
def start_poller_with_config(config, queue_config_name, access_key_id, secret_access_key, region, logger_file, log_level = ::Logger::ERROR)
|
46
|
+
SqsPoller::Logger.set_log_level(log_level)
|
47
|
+
SqsPoller::Logger.set_logger_file(logger_file)
|
48
|
+
|
49
|
+
::NewRelic::Agent.manual_start if ENV['START_NEW_RELIC_AGENT']
|
50
|
+
SqsPoller::Metrics.start_metrics_agent if ENV['START_LOCAL_METRICS_AGENT']
|
51
|
+
@logger = SqsPoller::Logger.get_new_logger("SqsPoller")
|
52
|
+
@logger.info "Started poller method"
|
53
|
+
queues_config = config[queue_config_name] || config[queue_config_name.to_sym]
|
54
|
+
total_poller_threads = get_total_poller_threads(queues_config)
|
55
|
+
worker_configuration = config[:worker_configuration]
|
56
|
+
total_worker_threads = get_total_worker_threads(worker_configuration, total_poller_threads)
|
57
|
+
waiting_tasks_ratio = get_waiting_tasks_ratio(worker_configuration)
|
58
|
+
aws_config = {
|
59
|
+
:access_key_id => access_key_id,
|
60
|
+
:secret_access_key => secret_access_key,
|
61
|
+
:region => region
|
62
|
+
}
|
63
|
+
|
64
|
+
task_queue = SizedQueue.new(total_worker_threads * waiting_tasks_ratio)
|
65
|
+
|
66
|
+
qc = SqsPoller::Poller::QueueController.start queues_config, task_queue, aws_config
|
67
|
+
unless qc.started?
|
68
|
+
@logger.error("Unable to start Queue Pollers.")
|
69
|
+
return
|
70
|
+
end
|
71
|
+
|
72
|
+
worker_task = worker_configuration[:worker_class].split('::').inject(Object) { |o, c| o.const_get c }.new(worker_configuration)
|
73
|
+
|
74
|
+
wc = SqsPoller::Process::WorkerController.start total_worker_threads, task_queue, worker_task
|
75
|
+
|
76
|
+
unless wc.started?
|
77
|
+
@logger.error("Unable to start Workers.")
|
78
|
+
return
|
79
|
+
end
|
80
|
+
|
81
|
+
wait
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
def start_poller(filename, queue_config_name, access_key_id, secret_access_key, region, log_filename = nil)
|
86
|
+
begin
|
87
|
+
puts "Starting poller"
|
88
|
+
config = YAML.load(ERB.new(IO.read(filename)).result)
|
89
|
+
config = sym(config)
|
90
|
+
|
91
|
+
if log_filename.nil? || log_filename.empty?
|
92
|
+
puts "Did not receive log file name"
|
93
|
+
fork do
|
94
|
+
Process.daemon
|
95
|
+
start_poller_with_config config, queue_config_name, access_key_id, secret_access_key, region, STDOUT, ::Logger::DEBUG
|
96
|
+
end
|
97
|
+
else
|
98
|
+
puts "Did receive log file name #{log_filename}"
|
99
|
+
#daemonize log_filename
|
100
|
+
puts "Daemonize log file name #{log_filename}"
|
101
|
+
start_poller_with_config config, queue_config_name, access_key_id, secret_access_key, region, STDOUT, ::Logger::INFO
|
102
|
+
end
|
103
|
+
rescue Exception => e
|
104
|
+
puts "#{e}"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def get_total_poller_threads(queues_config)
|
109
|
+
total_poller_threads = 0
|
110
|
+
queues_config.keys.each { |queue|
|
111
|
+
total_poller_threads += queues_config[queue][:polling_threads]
|
112
|
+
}
|
113
|
+
total_poller_threads
|
114
|
+
end
|
115
|
+
|
116
|
+
def get_waiting_tasks_ratio(worker_configuration)
|
117
|
+
waiting_tasks_ratio = worker_configuration[:waiting_tasks_ratio]
|
118
|
+
waiting_tasks_ratio = 1 if waiting_tasks_ratio.nil?
|
119
|
+
waiting_tasks_ratio
|
120
|
+
end
|
121
|
+
|
122
|
+
def get_total_worker_threads(worker_configuration, total_poller_threads)
|
123
|
+
worker_thread_count = worker_configuration[:concurrency]
|
124
|
+
worker_thread_count = total_poller_threads if worker_thread_count.nil?
|
125
|
+
worker_thread_count
|
126
|
+
end
|
127
|
+
|
128
|
+
def timeout
|
129
|
+
n_bytes = [42].pack('i').size
|
130
|
+
n_bits = n_bytes * 8
|
131
|
+
2 ** (n_bits - 2) - 1
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
def wait
|
137
|
+
t = Thread.new do
|
138
|
+
loop do
|
139
|
+
sleep(60 * 60)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
t.join
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'sqspoller/process/message_handler'
|
2
|
+
# DEPRECATED: This class is to support backward compatibility. This class will be removed once we updated all the config files updated.
|
3
|
+
module Sqspoller
|
4
|
+
|
5
|
+
class WorkerTask
|
6
|
+
|
7
|
+
def initialize(worker_configuration)
|
8
|
+
@message_handler = SqsPoller::Process::MessageHandler.new(worker_configuration)
|
9
|
+
end
|
10
|
+
|
11
|
+
def handle(message, message_id)
|
12
|
+
@message_handler.handle(message, message_id)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/lib/sqspoller.rb
ADDED
data/lib/test.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
worker_configuration:
|
2
|
+
worker_class: "Sqspoller::WorkerTask"
|
3
|
+
http_method: "post"
|
4
|
+
http_url: "http://localhost:5001/process"
|
5
|
+
concurrency: 50 # => Total Number of service threads - threads occupied by cron jobs - thread for heartbeat => 2*32 - 8 - 1 = 55
|
6
|
+
waiting_tasks_ratio: 2
|
7
|
+
production:
|
8
|
+
my-queue:
|
9
|
+
polling_threads: 4
|
10
|
+
max_number_of_messages: 10
|
11
|
+
message_types: [ ]
|
12
|
+
my-queue1:
|
13
|
+
polling_threads: 2
|
14
|
+
max_number_of_messages: 10
|
15
|
+
message_types: [ ]
|
data/sqspoller.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sqspoller/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "fourkites-sqspoller-v2"
|
8
|
+
spec.version = '1.0.0'
|
9
|
+
spec.authors = %w[anshul-fk nagarajan]
|
10
|
+
spec.email = %w[anshul@fourkites.com nagarajan.shanmugam@fourkites.com]
|
11
|
+
|
12
|
+
spec.summary = 'Gem to poll messages from SQS queue and process them'
|
13
|
+
spec.description = ''
|
14
|
+
spec.homepage = ''
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "bin"
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
|
24
|
+
spec.add_runtime_dependency "concurrent-ruby"
|
25
|
+
spec.add_runtime_dependency "rest-client"
|
26
|
+
spec.add_runtime_dependency 'aws-sdk', '~> 3'
|
27
|
+
spec.add_runtime_dependency 'ruby-metrics'
|
28
|
+
spec.add_runtime_dependency 'newrelic_rpm'
|
29
|
+
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fourkites-sqspoller-v2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- anshul-fk
|
8
|
+
- nagarajan
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2022-11-07 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.10'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1.10'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rake
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '10.0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '10.0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: concurrent-ruby
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rest-client
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: aws-sdk
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '3'
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '3'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: ruby-metrics
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :runtime
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: newrelic_rpm
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
type: :runtime
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
description: ''
|
113
|
+
email:
|
114
|
+
- anshul@fourkites.com
|
115
|
+
- nagarajan.shanmugam@fourkites.com
|
116
|
+
executables:
|
117
|
+
- run_sqs_poller
|
118
|
+
- sqs_poller.service
|
119
|
+
- sqs_poller_v2
|
120
|
+
extensions: []
|
121
|
+
extra_rdoc_files: []
|
122
|
+
files:
|
123
|
+
- ".gitignore"
|
124
|
+
- ".ruby-gemset"
|
125
|
+
- ".ruby-version"
|
126
|
+
- CODE_OF_CONDUCT.md
|
127
|
+
- Gemfile
|
128
|
+
- LICENSE
|
129
|
+
- README.md
|
130
|
+
- Rakefile
|
131
|
+
- bin/run_sqs_poller
|
132
|
+
- bin/sqs_poller.service
|
133
|
+
- bin/sqs_poller_v2
|
134
|
+
- images/SQS_Poller_V2.png
|
135
|
+
- install.sh
|
136
|
+
- lib/config/newrelic.yml
|
137
|
+
- lib/seahorse/stringio.rb
|
138
|
+
- lib/sqs-ruby-example-consume-queue.rb
|
139
|
+
- lib/sqs-ruby-example-create-queue.rb
|
140
|
+
- lib/sqspoller.rb
|
141
|
+
- lib/sqspoller/common/ring_buffer.rb
|
142
|
+
- lib/sqspoller/common/utils.rb
|
143
|
+
- lib/sqspoller/logger/logger.rb
|
144
|
+
- lib/sqspoller/metrics/log_reporter.rb
|
145
|
+
- lib/sqspoller/metrics/queue_stats_reporter.rb
|
146
|
+
- lib/sqspoller/metrics/sqs_poller_metrics.rb
|
147
|
+
- lib/sqspoller/poll/queue_controller.rb
|
148
|
+
- lib/sqspoller/poll/queue_poller.rb
|
149
|
+
- lib/sqspoller/process/message_handler.rb
|
150
|
+
- lib/sqspoller/process/task_finalizer.rb
|
151
|
+
- lib/sqspoller/process/task_worker.rb
|
152
|
+
- lib/sqspoller/process/worker_controller.rb
|
153
|
+
- lib/sqspoller/sqs_poller.rb
|
154
|
+
- lib/sqspoller/version.rb
|
155
|
+
- lib/sqspoller/worker_task.rb
|
156
|
+
- lib/test.yaml
|
157
|
+
- sqspoller.gemspec
|
158
|
+
homepage: ''
|
159
|
+
licenses: []
|
160
|
+
metadata: {}
|
161
|
+
post_install_message:
|
162
|
+
rdoc_options: []
|
163
|
+
require_paths:
|
164
|
+
- lib
|
165
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
166
|
+
requirements:
|
167
|
+
- - ">="
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: '0'
|
170
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
171
|
+
requirements:
|
172
|
+
- - ">="
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
version: '0'
|
175
|
+
requirements: []
|
176
|
+
rubygems_version: 3.3.14
|
177
|
+
signing_key:
|
178
|
+
specification_version: 4
|
179
|
+
summary: Gem to poll messages from SQS queue and process them
|
180
|
+
test_files: []
|