bellbro 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +2 -0
- data/Rakefile +2 -0
- data/bellbro.gemspec +26 -0
- data/lib/bellbro/notifier.rb +14 -0
- data/lib/bellbro/retryable.rb +67 -0
- data/lib/bellbro/sidekiq_utils.rb +74 -0
- data/lib/bellbro/trackable.rb +82 -0
- data/lib/bellbro/validator_redis_pool.rb +22 -0
- data/lib/bellbro/version.rb +3 -0
- data/lib/bellbro.rb +5 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5f5c30f13ccf46c9dd3ab5f9cf072da6fcbfb37e
|
4
|
+
data.tar.gz: 44a25b8367eaa4b1e5a32a9f6546784e96dd9b79
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ee77afd18e299eded56c87e06209d3b34eb9e2984c96c7ee0e00de4ecb98fd35836e0da04bee7f9b45596bbf38640b1744963f86d04e1c7028b89218849cb783
|
7
|
+
data.tar.gz: cf0a2c25af94a25d6e7ed6e0ec8fb992b7577adeb6674d0293c378278a688e9c306b81caa295476e96c986c94a954fe50ff5a134b4ad27f9c969ea4e728e5ed9
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Jon Stokes
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
data/Rakefile
ADDED
data/bellbro.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'bellbro/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "bellbro"
|
8
|
+
spec.version = Bellbro::VERSION
|
9
|
+
spec.authors = ["Jon Stokes"]
|
10
|
+
spec.email = ["jon@jonstokes.com"]
|
11
|
+
spec.summary = %q{Helps with sidekiq.}
|
12
|
+
spec.homepage = ""
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency "sidekiq"
|
21
|
+
spec.add_dependency "redis"
|
22
|
+
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Bellbro
|
2
|
+
module Notifier
|
3
|
+
def self.included(klass)
|
4
|
+
klass.extend(self)
|
5
|
+
end
|
6
|
+
|
7
|
+
def notify(logline, opts={})
|
8
|
+
domain_insert = @domain ? "[#{@domain}]": ""
|
9
|
+
error_insert = (opts[:type] == :error) ? "##ERROR## " : ""
|
10
|
+
complete_logline = "[#{self.class}](#{Thread.current.object_id})#{domain_insert}: #{error_insert}#{logline}"
|
11
|
+
$log.info complete_logline
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Bellbro
|
2
|
+
module Retryable
|
3
|
+
def self.included(klass)
|
4
|
+
klass.extend(self)
|
5
|
+
end
|
6
|
+
|
7
|
+
# Options:
|
8
|
+
# * :tries - Number of retries to perform. Defaults to 1.
|
9
|
+
# * :on - The Exception on which a retry will be performed. Defaults to Exception, which retries on any Exception.
|
10
|
+
#
|
11
|
+
# Example
|
12
|
+
# =======
|
13
|
+
# retryable(:tries => 1, :on => OpenURI::HTTPError) do
|
14
|
+
# # your code here
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
|
18
|
+
def retryable(options = {}, &block)
|
19
|
+
opts = { :tries => 5, :on => Exception, :sleep => 1 }.merge(options)
|
20
|
+
retry_exception, retries, interval = opts[:on], opts[:tries], opts[:sleep]
|
21
|
+
|
22
|
+
begin
|
23
|
+
return yield
|
24
|
+
rescue retry_exception
|
25
|
+
sleep interval
|
26
|
+
retry unless (retries -= 1).zero?
|
27
|
+
end
|
28
|
+
yield
|
29
|
+
end
|
30
|
+
|
31
|
+
def retryable_with_success(options = {}, &block)
|
32
|
+
opts = { :tries => 5, :on => Exception, :sleep => 1 }.merge(options)
|
33
|
+
retry_exception, retries, interval = opts[:on], opts[:tries], opts[:sleep]
|
34
|
+
|
35
|
+
success = false
|
36
|
+
begin
|
37
|
+
yield
|
38
|
+
success = true
|
39
|
+
rescue retry_exception
|
40
|
+
sleep interval
|
41
|
+
retry unless (retries -= 1).zero?
|
42
|
+
end
|
43
|
+
success
|
44
|
+
end
|
45
|
+
|
46
|
+
def retryable_with_aws(options = {}, &block)
|
47
|
+
# This is for use with AWS-based models. I find I get a lot of these timeouts and
|
48
|
+
# OpenSSL errors, and sometimes the connection dies and I need to create a new
|
49
|
+
# connection object. I put this in a method called aws_connect!.
|
50
|
+
#
|
51
|
+
opts = { :tries => 10, :on => Exception, :sleep => 1 }.merge(options)
|
52
|
+
retry_exception, retries, interval = opts[:on], opts[:tries], opts[:sleep]
|
53
|
+
|
54
|
+
begin
|
55
|
+
return yield
|
56
|
+
rescue OpenSSL::SSL::SSLError, Timeout::Error
|
57
|
+
sleep interval
|
58
|
+
aws_connect!
|
59
|
+
retry unless (retries -= 1).zero?
|
60
|
+
rescue retry_exception
|
61
|
+
sleep interval
|
62
|
+
retry unless (retries -= 1).zero?
|
63
|
+
end
|
64
|
+
yield
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Bellbro
|
2
|
+
module SidekiqUtils
|
3
|
+
|
4
|
+
def workers
|
5
|
+
Sidekiq::Workers.new.map do |process_id, thread_id, worker|
|
6
|
+
worker
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def workers_for_queue(q)
|
11
|
+
workers.select do |worker|
|
12
|
+
worker_queue(worker) == q
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def workers_for_class(klass)
|
17
|
+
workers.select do |worker|
|
18
|
+
worker_class(worker) == klass
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def worker_jid(worker)
|
23
|
+
worker["payload"]["jid"] if worker["payload"]
|
24
|
+
end
|
25
|
+
|
26
|
+
def worker_domain(worker)
|
27
|
+
worker["payload"]["args"].first["domain"] if worker["payload"] && worker["payload"]["args"].try(:any?)
|
28
|
+
end
|
29
|
+
|
30
|
+
def worker_time(worker)
|
31
|
+
worker["run_at"]
|
32
|
+
end
|
33
|
+
|
34
|
+
def worker_class(worker)
|
35
|
+
worker["payload"]["class"] if worker["payload"]
|
36
|
+
end
|
37
|
+
|
38
|
+
def worker_queue(worker)
|
39
|
+
worker["queue"]
|
40
|
+
end
|
41
|
+
|
42
|
+
def jobs_for_queue(q)
|
43
|
+
Sidekiq::Queue.new(q)
|
44
|
+
end
|
45
|
+
|
46
|
+
def jobs_for_class(klass)
|
47
|
+
queues.map do |q|
|
48
|
+
jobs_for_queue(q).select { |job| job.klass == klass }
|
49
|
+
end.flatten
|
50
|
+
end
|
51
|
+
|
52
|
+
def job_domain(job)
|
53
|
+
job.args.first["domain"] if job.args.any?
|
54
|
+
end
|
55
|
+
|
56
|
+
def job_jid(job)
|
57
|
+
job.jid
|
58
|
+
end
|
59
|
+
|
60
|
+
def number_of_active_workers(q_name)
|
61
|
+
workers_for_queue(q_name).count
|
62
|
+
end
|
63
|
+
|
64
|
+
def queues
|
65
|
+
Sidekiq::Stats::Queues.new.lengths.keys
|
66
|
+
end
|
67
|
+
|
68
|
+
def clear_all_queues
|
69
|
+
queues.each do |q|
|
70
|
+
clear_queue(q)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Bellbro
|
2
|
+
module Trackable
|
3
|
+
include Bellbro::Retryable
|
4
|
+
attr_reader :record
|
5
|
+
|
6
|
+
def track(opts={})
|
7
|
+
return if @log_record_schema # Ignore repeated calls to #track, as in RefreshLinksWorker
|
8
|
+
opts.symbolize_keys!
|
9
|
+
@log_record_schema = self.class::LOG_RECORD_SCHEMA
|
10
|
+
@write_interval = opts[:write_interval] || 500
|
11
|
+
@count = 0
|
12
|
+
@tracking = true
|
13
|
+
initialize_log_record
|
14
|
+
status_update(true)
|
15
|
+
end
|
16
|
+
|
17
|
+
def status_update(force = false)
|
18
|
+
return unless force || ((@count += 1) % @write_interval) == 0
|
19
|
+
retryable { $log.info(@record.to_json) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def record_set(attr, value)
|
23
|
+
attr = attr.to_sym
|
24
|
+
validate(attr => value)
|
25
|
+
@record[:data][attr] = value
|
26
|
+
end
|
27
|
+
|
28
|
+
def record_incr(attr)
|
29
|
+
attr = attr.to_sym
|
30
|
+
validate(attr => 1)
|
31
|
+
@record[:data][attr] += 1
|
32
|
+
end
|
33
|
+
|
34
|
+
def stop_tracking
|
35
|
+
@record[:complete] = true
|
36
|
+
@record[:stopped] = Time.now.utc.iso8601
|
37
|
+
@tracking = false
|
38
|
+
status_update(true)
|
39
|
+
end
|
40
|
+
|
41
|
+
def tracking?
|
42
|
+
!!@tracking
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def initialize_log_record
|
48
|
+
@record = {
|
49
|
+
host: Socket.gethostname,
|
50
|
+
agent: {
|
51
|
+
name: "#{self.class.name}",
|
52
|
+
thread: "#{Thread.current.object_id}",
|
53
|
+
jid: self.jid,
|
54
|
+
},
|
55
|
+
domain: @site.try(:domain) || @domain,
|
56
|
+
complete: false,
|
57
|
+
started: Time.now.utc.iso8601,
|
58
|
+
data: {}
|
59
|
+
}
|
60
|
+
|
61
|
+
self.class::LOG_RECORD_SCHEMA.each do |k, v|
|
62
|
+
if v == Integer
|
63
|
+
@record[:data][k] = 0
|
64
|
+
else
|
65
|
+
@record[:data][k] = v.new
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def log_record_attributes
|
71
|
+
@log_record_schema.keys + [:jid, :agent, :archived]
|
72
|
+
end
|
73
|
+
|
74
|
+
def validate(attrs)
|
75
|
+
attrs.each do |attr, value|
|
76
|
+
raise "Invalid attribute #{attr}" unless log_record_attributes.include?(attr)
|
77
|
+
raise "Invalid type for #{attr}" unless [value.class, value.class.superclass].include?(self.class::LOG_RECORD_SCHEMA[attr])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Bellbro
|
2
|
+
module RedisPool
|
3
|
+
def self.included(klass)
|
4
|
+
klass.extend(self)
|
5
|
+
end
|
6
|
+
|
7
|
+
def with_redis(&block)
|
8
|
+
retryable(sleep: 0.5) do
|
9
|
+
redis_pool.with &block
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def redis_pool
|
14
|
+
@redis_pool
|
15
|
+
end
|
16
|
+
|
17
|
+
def redis_pool=(pool)
|
18
|
+
@redis_pool = pool
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
data/lib/bellbro.rb
ADDED
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bellbro
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jon Stokes
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - '>='
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '0'
|
19
|
+
name: sidekiq
|
20
|
+
prerelease: false
|
21
|
+
type: :runtime
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
name: redis
|
34
|
+
prerelease: false
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.7'
|
47
|
+
name: bundler
|
48
|
+
prerelease: false
|
49
|
+
type: :development
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.7'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ~>
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '10.0'
|
61
|
+
name: rake
|
62
|
+
prerelease: false
|
63
|
+
type: :development
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- jon@jonstokes.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- .gitignore
|
77
|
+
- Gemfile
|
78
|
+
- LICENSE.txt
|
79
|
+
- README.md
|
80
|
+
- Rakefile
|
81
|
+
- bellbro.gemspec
|
82
|
+
- lib/bellbro.rb
|
83
|
+
- lib/bellbro/notifier.rb
|
84
|
+
- lib/bellbro/retryable.rb
|
85
|
+
- lib/bellbro/sidekiq_utils.rb
|
86
|
+
- lib/bellbro/trackable.rb
|
87
|
+
- lib/bellbro/validator_redis_pool.rb
|
88
|
+
- lib/bellbro/version.rb
|
89
|
+
homepage: ''
|
90
|
+
licenses:
|
91
|
+
- MIT
|
92
|
+
metadata: {}
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - '>='
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 2.4.5
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: Helps with sidekiq.
|
113
|
+
test_files: []
|