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 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
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+
16
+ /.idea/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in bellbro.gemspec
4
+ gemspec
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
@@ -0,0 +1,2 @@
1
+ # bellbro
2
+ A collection of utils that I use in my apps when working the sidekiq. You may or may not find them useful.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
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
@@ -0,0 +1,3 @@
1
+ module Bellbro
2
+ VERSION = "0.0.1"
3
+ end
data/lib/bellbro.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "bellbro/version"
2
+
3
+ module Bellbro
4
+ # Your code goes here...
5
+ end
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: []