upperkut 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,19 +0,0 @@
1
- require_relative '../lib/upperkut/worker'
2
- require_relative '../lib/upperkut/strategies/scheduled_queue'
3
-
4
- class ScheduledWorker
5
- include Upperkut::Worker
6
-
7
- setup_upperkut do |config|
8
- config.strategy = Upperkut::Strategies::ScheduledQueue.new(
9
- self,
10
- batch_size: 200
11
- )
12
- end
13
-
14
- def perform(items)
15
- items.each do |item|
16
- puts "event dispatched: #{item.inspect}"
17
- end
18
- end
19
- end
@@ -1,42 +0,0 @@
1
- require_relative '../lib/upperkut/worker'
2
- require_relative '../lib/upperkut/logging'
3
-
4
- class ClientMiddleware
5
- def call(worker, items)
6
- logger = Upperkut::Logging.logger
7
-
8
- logger.info("inserting worker=#{worker} items=#{items.count}")
9
- yield
10
- logger.info("inserted worker=#{worker} items=#{items.count}")
11
- end
12
- end
13
-
14
- class MyMiddleware
15
- def call(worker, items)
16
- logger = Upperkut::Logging.logger
17
-
18
- logger.info("performing worker=#{worker} items=#{items.count}")
19
- yield
20
- logger.info("performed worker=#{worker} items=#{items.count}")
21
- end
22
- end
23
-
24
- class WithMiddlewares
25
- include Upperkut::Worker
26
-
27
- setup_upperkut do |config|
28
- config.server_middlewares do |chain|
29
- chain.add MyMiddleware
30
- end
31
-
32
- config.client_middlewares do |chain|
33
- chain.add ClientMiddleware
34
- end
35
- end
36
-
37
- def perform(_items)
38
- puts 'executing.........'
39
- exec_time = rand(80..200)
40
- sleep (exec_time.to_f / 1000.to_f)
41
- end
42
- end
data/lib/upperkut/cli.rb DELETED
@@ -1,100 +0,0 @@
1
- require 'optparse'
2
- require_relative '../upperkut'
3
- require_relative 'manager'
4
- require_relative 'logging'
5
-
6
- module Upperkut
7
- class CLI
8
- def initialize(args = ARGV)
9
- @options = {}
10
- @logger = Upperkut::Logging.logger
11
-
12
- parse_options(args)
13
- end
14
-
15
- def start
16
- if target_required = @options[:require]
17
- if File.directory?(target_required)
18
- require 'rails'
19
- if ::Rails::VERSION::MAJOR == 4
20
- require File.expand_path("#{@options[:require]}/config/application.rb")
21
- ::Rails::Application.initializer 'upperkut.eager_load' do
22
- ::Rails.application.config.eager_load = true
23
- end
24
-
25
- require File.expand_path("#{@options[:require]}/config/environment.rb")
26
- else
27
- require File.expand_path("#{@options[:require]}/config/environment.rb")
28
- end
29
- else
30
- require target_required
31
- end
32
- end
33
-
34
- if log_level = @options[:log_level]
35
- @logger.level = log_level
36
- end
37
-
38
- @options[:logger] = @logger
39
-
40
- manager = Manager.new(@options)
41
-
42
- @logger.info(@options)
43
-
44
- r, w = IO.pipe
45
- signals = %w[INT TERM]
46
-
47
- signals.each do |signal|
48
- trap signal do
49
- w.puts(signal)
50
- end
51
- end
52
-
53
- begin
54
- manager.run
55
- while readable_io = IO.select([r])
56
- signal = readable_io.first[0].gets.strip
57
- handle_signal(signal)
58
- end
59
- rescue Interrupt
60
- timeout = Integer(ENV['UPPERKUT_TIMEOUT'] || 8)
61
- @logger.info(
62
- "Stopping managers, wait for #{timeout} seconds and them kill processors"
63
- )
64
-
65
- manager.stop
66
- sleep(timeout)
67
- manager.kill
68
- exit(0)
69
- end
70
- end
71
-
72
- private
73
-
74
- def handle_signal(sig)
75
- case sig
76
- when 'INT'
77
- raise Interrupt
78
- when 'TERM'
79
- raise Interrupt
80
- end
81
- end
82
-
83
- def parse_options(args)
84
- OptionParser.new do |o|
85
- o.on('-w', '--worker WORKER', 'Define worker to be processed') do |arg|
86
- @options[:worker] = arg
87
- end
88
- o.on('-r', '--require FILE', 'Indicate a file to be required') do |arg|
89
- @options[:require] = arg
90
- end
91
- o.on('-c', '--concurrency INT', 'Numbers of threads to spawn') do |arg|
92
- @options[:concurrency] = Integer(arg)
93
- end
94
- o.on('-l', '--log-level LEVEL', 'Log level') do |arg|
95
- @options[:log_level] = arg.to_i
96
- end
97
- end.parse!(args)
98
- end
99
- end
100
- end
@@ -1,18 +0,0 @@
1
- begin
2
- require 'active_support/core_ext/string/inflections'
3
- rescue LoadError
4
- unless ''.respond_to?(:constantize)
5
- class String
6
- def constantize
7
- names = split('::')
8
- names.shift if names.empty? || names.first.empty?
9
-
10
- constant = Object
11
- names.each do |name|
12
- constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
13
- end
14
- constant
15
- end
16
- end
17
- end
18
- end
data/lib/upperkut/item.rb DELETED
@@ -1,22 +0,0 @@
1
- require 'securerandom'
2
-
3
- module Upperkut
4
- class Item
5
- attr_reader :id, :body, :enqueued_at
6
-
7
- def initialize(id:, body:, enqueued_at: nil)
8
- @id = id
9
- @body = body
10
- @enqueued_at = enqueued_at || Time.now.utc.to_i
11
- @nacked = false
12
- end
13
-
14
- def nack
15
- @nacked = true
16
- end
17
-
18
- def nacked?
19
- @nacked
20
- end
21
- end
22
- end
@@ -1,36 +0,0 @@
1
- require 'logger'
2
- require 'time'
3
- require 'socket'
4
-
5
- module Upperkut
6
- module Logging
7
- class DefaultFormatter < Logger::Formatter
8
- def call(severity, time, _program_name, message)
9
- "upperkut: #{time.utc.iso8601(3)} hostname=#{Socket.gethostname} "\
10
- "pid=#{::Process.pid} severity=#{severity} #{format_message(message)}\n"
11
- end
12
-
13
- private
14
-
15
- def format_message(message)
16
- return "msg=#{message} " unless message.is_a?(Hash)
17
-
18
- message.each_with_object('') do |(k, v), memo|
19
- memo << "#{k}=#{v}\s"
20
- memo
21
- end
22
- end
23
- end
24
-
25
- def self.initialize_logger
26
- logger = Logger.new($stdout)
27
- logger.level = Logger::INFO
28
- logger.formatter = DefaultFormatter.new
29
- logger
30
- end
31
-
32
- def self.logger
33
- @logger ||= initialize_logger
34
- end
35
- end
36
- end
@@ -1,50 +0,0 @@
1
- require_relative 'core_ext'
2
- require_relative 'worker_thread'
3
- require_relative 'logging'
4
- require_relative 'worker'
5
-
6
- module Upperkut
7
- class Manager
8
- attr_accessor :worker
9
- attr_reader :stopped, :logger, :concurrency
10
-
11
- def initialize(opts = {})
12
- self.worker = opts.fetch(:worker).constantize
13
- @concurrency = opts.fetch(:concurrency, 1)
14
- @logger = opts.fetch(:logger, Logging.logger)
15
-
16
- @stopped = false
17
- @threads = []
18
- end
19
-
20
- def run
21
- @concurrency.times do
22
- spawn_thread
23
- end
24
- end
25
-
26
- def stop
27
- @stopped = true
28
- @threads.each(&:stop)
29
- end
30
-
31
- def kill
32
- @threads.each(&:kill)
33
- end
34
-
35
- def notify_killed_processor(thread)
36
- @threads.delete(thread)
37
- spawn_thread unless @stopped
38
- end
39
-
40
- private
41
-
42
- def spawn_thread
43
- processor = Processor.new(worker, logger)
44
-
45
- thread = WorkerThread.new(self, processor)
46
- @threads << thread
47
- thread.run
48
- end
49
- end
50
- end
@@ -1,35 +0,0 @@
1
- module Upperkut
2
- module Middleware
3
- class Chain
4
- attr_reader :items
5
-
6
- def initialize
7
- @items = []
8
- end
9
-
10
- def add(item)
11
- return @items if @items.include?(item)
12
-
13
- @items << item
14
- end
15
-
16
- def remove(item)
17
- @items.delete(item)
18
- end
19
-
20
- def invoke(*args)
21
- chain = @items.map(&:new)
22
-
23
- traverse_chain = lambda do
24
- if chain.empty?
25
- yield
26
- else
27
- chain.shift.call(*args, &traverse_chain)
28
- end
29
- end
30
-
31
- traverse_chain.call
32
- end
33
- end
34
- end
35
- end
@@ -1,11 +0,0 @@
1
- module Upperkut
2
- module Middlewares
3
- class Datadog
4
- def call(worker, _items)
5
- ::Datadog.tracer.trace(worker.name) do
6
- yield
7
- end
8
- end
9
- end
10
- end
11
- end
@@ -1,23 +0,0 @@
1
- module Upperkut
2
- module Middlewares
3
- class NewRelic
4
- include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
5
-
6
- def call(worker, _items)
7
- perform_action_with_newrelic_trace(trace_args(worker)) do
8
- yield
9
- end
10
- end
11
-
12
- private
13
-
14
- def trace_args(worker)
15
- {
16
- name: 'perform',
17
- class_name: worker.name,
18
- category: 'OtherTransaction/Upperkut'
19
- }
20
- end
21
- end
22
- end
23
- end
@@ -1,25 +0,0 @@
1
- module Upperkut
2
- module Middlewares
3
- class Rollbar
4
- def call(worker, items)
5
- ::Rollbar.reset_notifier!
6
- yield
7
- rescue Exception => e
8
- handle_exception(e, worker, items)
9
- raise e
10
- end
11
-
12
- private
13
-
14
- def handle_exception(e, worker, items)
15
- scope = {
16
- framework: "Upperkut #{::Upperkut::VERSION}",
17
- request: { params: { items_size: items.size } },
18
- context: worker.name
19
- }
20
-
21
- ::Rollbar.scope(scope).error(e, use_exception_level_filters: true)
22
- end
23
- end
24
- end
25
- end
@@ -1,64 +0,0 @@
1
- require_relative 'logging'
2
-
3
- module Upperkut
4
- class Processor
5
- def initialize(worker, logger = Logging.logger)
6
- @worker = worker
7
- @strategy = worker.strategy
8
- @worker_instance = worker.new
9
- @logger = logger
10
- end
11
-
12
- def process
13
- items = @worker.fetch_items.freeze
14
- return unless items.any?
15
-
16
- @worker.server_middlewares.invoke(@worker, items) do
17
- @worker_instance.perform(items)
18
- end
19
-
20
- nacked_items, pending_ack_items = items.partition(&:nacked?)
21
- @strategy.nack(nacked_items) if nacked_items.any?
22
- @strategy.ack(pending_ack_items) if pending_ack_items.any?
23
- rescue StandardError => error
24
- @logger.error(
25
- action: :handle_execution_error,
26
- ex: error.to_s,
27
- backtrace: error.backtrace.join("\n"),
28
- item_size: Array(items).size
29
- )
30
-
31
- if items
32
- if @worker_instance.respond_to?(:handle_error)
33
- @worker_instance.handle_error(error, items)
34
- return
35
- end
36
-
37
- @strategy.nack(items)
38
- end
39
-
40
- raise error
41
- end
42
-
43
- def blocking_process
44
- sleeping_time = 0
45
-
46
- loop do
47
- break if @stopped
48
-
49
- if @strategy.process?
50
- sleeping_time = 0
51
- process
52
- next
53
- end
54
-
55
- sleeping_time += sleep(@worker.setup.polling_interval)
56
- @logger.debug(sleeping_time: sleeping_time)
57
- end
58
- end
59
-
60
- def stop
61
- @stopped = true
62
- end
63
- end
64
- end
@@ -1,29 +0,0 @@
1
- require 'connection_pool'
2
- require 'redis'
3
-
4
- module Upperkut
5
- class RedisPool
6
- DEFAULT_OPTIONS = {
7
- pool_timeout: 1, # pool related option
8
- size: 2, # pool related option
9
- connect_timeout: 0.2,
10
- read_timeout: 5.0,
11
- write_timeout: 0.5
12
- }.freeze
13
-
14
- def initialize(options)
15
- @options = DEFAULT_OPTIONS.merge(url: ENV['REDIS_URL'])
16
- .merge(options)
17
-
18
- # Extract pool related options
19
- @size = @options.delete(:size)
20
- @pool_timeout = @options.delete(:pool_timeout)
21
- end
22
-
23
- def create
24
- ConnectionPool.new(timeout: @pool_timeout, size: @size) do
25
- Redis.new(@options)
26
- end
27
- end
28
- end
29
- end
@@ -1,56 +0,0 @@
1
- module Upperkut
2
- module Strategies
3
- class Base
4
- # Public: Ingests the event into strategy.
5
- #
6
- # items - The Array of items do be inserted.
7
- #
8
- # Returns true when success, raise when error.
9
- def push_items(_items = [])
10
- raise NotImplementedError
11
- end
12
-
13
- # Public: Retrieve events from Strategy.
14
- #
15
- # batch_size: # of items to be retrieved.
16
- #
17
- # Returns an Array containing events as hash.
18
- def fetch_items(_batch_size)
19
- raise NotImplementedError
20
- end
21
-
22
- # Public: Clear all data related to the strategy.
23
- def clear
24
- raise NotImplementedError
25
- end
26
-
27
- # Public: Confirms that items have been processed successfully.
28
- #
29
- # items - The Array of items do be confirmed.
30
- def ack(_items)
31
- raise NotImplementedError
32
- end
33
-
34
- # Public: Informs that items have been not processed successfully and therefore must be re-processed.
35
- #
36
- # items - The Array of items do be unacknowledged.
37
- def nack(_items)
38
- raise NotImplementedError
39
- end
40
-
41
- # Public: Tells when to execute the event processing,
42
- # when this condition is met so the events are dispatched to
43
- # the worker.
44
- def process?
45
- raise NotImplementedError
46
- end
47
-
48
- # Public: Consolidated strategy metrics.
49
- #
50
- # Returns hash containing metric name and values.
51
- def metrics
52
- raise NotImplementedError
53
- end
54
- end
55
- end
56
- end