coverband 1.5.4 → 2.0.0.alpha
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 +4 -4
- data/.gitignore +3 -0
- data/.travis.yml +3 -0
- data/Gemfile +2 -1
- data/Rakefile +5 -3
- data/coverband.gemspec +27 -23
- data/lib/coverband.rb +10 -14
- data/lib/coverband/adapters/file_store.rb +6 -7
- data/lib/coverband/adapters/memory_cache_store.rb +8 -5
- data/lib/coverband/adapters/redis_store.rb +10 -50
- data/lib/coverband/baseline.rb +5 -5
- data/lib/coverband/collectors/base.rb +140 -0
- data/lib/coverband/collectors/coverage.rb +148 -0
- data/lib/coverband/collectors/trace.rb +100 -0
- data/lib/coverband/configuration.rb +8 -10
- data/lib/coverband/middleware.rb +5 -5
- data/lib/coverband/reporters/base.rb +26 -31
- data/lib/coverband/reporters/console_report.rb +2 -3
- data/lib/coverband/reporters/simple_cov_report.rb +5 -6
- data/lib/coverband/s3_report_writer.rb +7 -8
- data/lib/coverband/s3_web.rb +3 -5
- data/lib/coverband/tasks.rb +23 -26
- data/lib/coverband/version.rb +3 -1
- data/test/benchmarks/benchmark.rake +38 -32
- data/test/benchmarks/dog.rb +3 -3
- data/test/fake_app/basic_rack.rb +4 -2
- data/test/test_helper.rb +17 -11
- data/test/unit/adapters_file_store_test.rb +12 -11
- data/test/unit/adapters_memory_cache_store_test.rb +3 -4
- data/test/unit/adapters_redis_store_test.rb +42 -118
- data/test/unit/baseline_test.rb +17 -20
- data/test/unit/collectors_base_test.rb +96 -0
- data/test/unit/collectors_coverage_test.rb +137 -0
- data/test/unit/collectors_trace_test.rb +96 -0
- data/test/unit/configuration_test.rb +8 -8
- data/test/unit/dog.rb +3 -1
- data/test/unit/middleware_test.rb +70 -61
- data/test/unit/reports_base_test.rb +62 -62
- data/test/unit/reports_console_test.rb +18 -21
- data/test/unit/reports_simple_cov_test.rb +23 -26
- data/test/unit/s3_report_writer_test.rb +6 -8
- data/test/unit/s3_web_test.rb +2 -1
- metadata +45 -25
- data/lib/coverband/base.rb +0 -210
- data/test/unit/base_test.rb +0 -100
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 578fbbc18bb6563f7d6568ba1b62ca49957f08e9
|
4
|
+
data.tar.gz: 0b4fd748dfedd42479f770bf9d853910d589d0f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3cfc0686746b6100abeae7345fa536028d8ba7c9a4168fbfee5b62f66f71e4185bb0dfa9f93d10d97543898b1b4a16ffacd3e7413c009dff645ca012df37fdce
|
7
|
+
data.tar.gz: 3d5573fc51c3cb2efbbf7ea79cd4711bde18950d18324a4f2d72cb3f51f1a3a68934d29ac6a60154a9d2548f8661c47982f92af39dde49e742f7cb128f046d1e
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -1,13 +1,15 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
2
4
|
|
3
5
|
import 'test/benchmarks/benchmark.rake'
|
4
6
|
|
5
|
-
task :
|
7
|
+
task default: :test
|
6
8
|
require 'rake/testtask'
|
7
9
|
Rake::TestTask.new(:test) do |test|
|
8
10
|
test.libs << 'lib' << 'test'
|
9
11
|
# exclude benchmark from the tests as the way it functions resets code coverage during executions
|
10
|
-
#test.pattern = 'test/unit/*_test.rb'
|
12
|
+
# test.pattern = 'test/unit/*_test.rb'
|
11
13
|
# using test files opposed to pattern as it outputs which files are run
|
12
14
|
test.test_files = FileList['test/unit/*_test.rb']
|
13
15
|
test.verbose = true
|
data/coverband.gemspec
CHANGED
@@ -1,34 +1,38 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'coverband/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
8
|
+
spec.name = 'coverband'
|
8
9
|
spec.version = Coverband::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.description =
|
12
|
-
spec.summary =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
10
|
+
spec.authors = ['Dan Mayer']
|
11
|
+
spec.email = ['dan@mayerdan.com']
|
12
|
+
spec.description = 'Rack middleware to help measure production code usage (LOC runtime usage)'
|
13
|
+
spec.summary = 'Rack middleware to help measure production code usage (LOC runtime usage)'
|
14
|
+
spec.homepage = 'https://github.com/danmayer/coverband'
|
15
|
+
spec.license = 'MIT'
|
15
16
|
|
16
|
-
spec.files = `git ls-files`.split(
|
17
|
+
spec.files = `git ls-files`.split("\n")
|
17
18
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = [
|
20
|
+
spec.require_paths = ['lib']
|
20
21
|
|
21
|
-
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
-
spec.add_development_dependency "rake"
|
23
|
-
spec.add_development_dependency "mocha", "~> 0.14.0"
|
24
|
-
spec.add_development_dependency "rack"
|
25
|
-
spec.add_development_dependency "rack-test"
|
26
|
-
spec.add_development_dependency "test-unit"
|
27
|
-
spec.add_development_dependency 'sinatra'
|
28
|
-
spec.add_development_dependency 'classifier-reborn'
|
29
22
|
spec.add_development_dependency 'aws-sdk', '~> 2'
|
30
|
-
spec.
|
31
|
-
spec.
|
32
|
-
|
33
|
-
spec.
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
24
|
+
spec.add_development_dependency 'classifier-reborn'
|
25
|
+
spec.add_development_dependency 'mocha', '~> 0.14.0'
|
26
|
+
spec.add_development_dependency 'rack'
|
27
|
+
spec.add_development_dependency 'rack-test'
|
28
|
+
spec.add_development_dependency 'rake'
|
29
|
+
spec.add_development_dependency 'sinatra'
|
30
|
+
spec.add_development_dependency 'test-unit'
|
31
|
+
# add when debugging
|
32
|
+
# require 'byebug'; byebug
|
33
|
+
spec.add_development_dependency 'byebug'
|
34
|
+
spec.add_runtime_dependency 'json'
|
35
|
+
spec.add_runtime_dependency 'simplecov', '> 0.11.1'
|
36
|
+
# TODO: make redis optional dependancy as we add additional adapters
|
37
|
+
spec.add_runtime_dependency 'redis'
|
34
38
|
end
|
data/lib/coverband.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'logger'
|
2
4
|
require 'json'
|
3
|
-
#
|
5
|
+
# TODO: move to only be request if using redis store
|
4
6
|
require 'redis'
|
5
7
|
|
6
8
|
require 'coverband/version'
|
@@ -8,7 +10,9 @@ require 'coverband/configuration'
|
|
8
10
|
require 'coverband/adapters/redis_store'
|
9
11
|
require 'coverband/adapters/memory_cache_store'
|
10
12
|
require 'coverband/adapters/file_store'
|
11
|
-
require 'coverband/base'
|
13
|
+
require 'coverband/collectors/base'
|
14
|
+
require 'coverband/collectors/trace'
|
15
|
+
require 'coverband/collectors/coverage'
|
12
16
|
require 'coverband/baseline'
|
13
17
|
require 'coverband/reporters/base'
|
14
18
|
require 'coverband/reporters/simple_cov_report'
|
@@ -23,27 +27,19 @@ module Coverband
|
|
23
27
|
attr_accessor :configuration_data
|
24
28
|
end
|
25
29
|
|
26
|
-
# this method is left for backwards compatibility with existing configs
|
27
|
-
def self.parse_baseline(baseline_file = './tmp/coverband_baseline.json')
|
28
|
-
Coverband::Baseline.parse_baseline(baseline_file)
|
29
|
-
end
|
30
|
-
|
31
30
|
def self.configure(file = nil)
|
32
31
|
configuration
|
33
32
|
if block_given?
|
34
33
|
yield(configuration)
|
34
|
+
elsif File.exist?(CONFIG_FILE)
|
35
|
+
file ||= CONFIG_FILE
|
36
|
+
require file
|
35
37
|
else
|
36
|
-
|
37
|
-
file ||= CONFIG_FILE
|
38
|
-
require file
|
39
|
-
else
|
40
|
-
raise ArgumentError, "configure requires a block or the existance of a #{CONFIG_FILE} in your project"
|
41
|
-
end
|
38
|
+
raise ArgumentError, "configure requires a block or the existance of a #{CONFIG_FILE} in your project"
|
42
39
|
end
|
43
40
|
end
|
44
41
|
|
45
42
|
def self.configuration
|
46
43
|
self.configuration_data ||= Configuration.new
|
47
44
|
end
|
48
|
-
|
49
45
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Coverband
|
2
4
|
module Adapters
|
3
5
|
class FileStore
|
4
6
|
attr_accessor :path
|
5
7
|
|
6
|
-
def initialize(path,
|
8
|
+
def initialize(path, _opts = {})
|
7
9
|
@path = path
|
8
10
|
|
9
11
|
config_dir = File.dirname(@path)
|
@@ -11,18 +13,16 @@ module Coverband
|
|
11
13
|
end
|
12
14
|
|
13
15
|
def clear!
|
14
|
-
if File.exist?(path)
|
15
|
-
File.delete(path)
|
16
|
-
end
|
16
|
+
File.delete(path) if File.exist?(path)
|
17
17
|
end
|
18
18
|
|
19
19
|
def save_report(report)
|
20
20
|
results = existing_data(path)
|
21
21
|
report.each_pair do |file, values|
|
22
|
-
if results.
|
22
|
+
if results.key?(file)
|
23
23
|
# convert the keys to "3" opposed to 3
|
24
24
|
values = JSON.parse(values.to_json)
|
25
|
-
results[file].merge!(
|
25
|
+
results[file].merge!(values) { |_k, old_v, new_v| old_v.to_i + new_v.to_i }
|
26
26
|
else
|
27
27
|
results[file] = values
|
28
28
|
end
|
@@ -53,7 +53,6 @@ module Coverband
|
|
53
53
|
{}
|
54
54
|
end
|
55
55
|
end
|
56
|
-
|
57
56
|
end
|
58
57
|
end
|
59
58
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Coverband
|
2
4
|
module Adapters
|
3
5
|
class MemoryCacheStore
|
@@ -20,10 +22,11 @@ module Coverband
|
|
20
22
|
store.save_report(filtered_files) if filtered_files.any?
|
21
23
|
end
|
22
24
|
|
25
|
+
# rubocop:disable Lint/IneffectiveAccessModifier
|
23
26
|
private
|
24
27
|
|
25
28
|
def self.files_cache
|
26
|
-
@files_cache ||=
|
29
|
+
@files_cache ||= {}
|
27
30
|
end
|
28
31
|
|
29
32
|
def files_cache
|
@@ -31,16 +34,16 @@ module Coverband
|
|
31
34
|
end
|
32
35
|
|
33
36
|
def filter(files)
|
34
|
-
files.each_with_object(
|
35
|
-
#first time we see a file, we pre-init the in memory cache to whatever is in store(redis)
|
37
|
+
files.each_with_object({}) do |(file, lines), filtered_file_hash|
|
38
|
+
# first time we see a file, we pre-init the in memory cache to whatever is in store(redis)
|
36
39
|
line_cache = files_cache[file] ||= Set.new(store.covered_lines_for_file(file))
|
37
40
|
lines.reject! do |line|
|
38
|
-
line_cache.include?(line) ? true : (line_cache << line
|
41
|
+
line_cache.include?(line) ? true : (line_cache << line && false)
|
39
42
|
end
|
40
43
|
filtered_file_hash[file] = lines if lines.any?
|
41
44
|
end
|
42
45
|
end
|
43
|
-
|
46
|
+
# rubocop:enable Lint/IneffectiveAccessModifier
|
44
47
|
end
|
45
48
|
end
|
46
49
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Coverband
|
2
4
|
module Adapters
|
3
5
|
class RedisStore
|
@@ -5,10 +7,6 @@ module Coverband
|
|
5
7
|
|
6
8
|
def initialize(redis, opts = {})
|
7
9
|
@redis = redis
|
8
|
-
#remove check for coverband 2.0
|
9
|
-
@_sadd_supports_array = recent_gem_version? && recent_server_version?
|
10
|
-
#possibly drop array storage for 2.0
|
11
|
-
@store_as_array = opts.fetch(:array){ false }
|
12
10
|
end
|
13
11
|
|
14
12
|
def clear!
|
@@ -17,20 +15,10 @@ module Coverband
|
|
17
15
|
end
|
18
16
|
|
19
17
|
def save_report(report)
|
20
|
-
|
21
|
-
redis.pipelined do
|
22
|
-
store_array(BASE_KEY, report.keys)
|
23
|
-
|
24
|
-
report.each do |file, lines|
|
25
|
-
store_array("#{BASE_KEY}.#{file}", lines.keys)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
else
|
29
|
-
store_array(BASE_KEY, report.keys)
|
18
|
+
store_array(BASE_KEY, report.keys)
|
30
19
|
|
31
|
-
|
32
|
-
|
33
|
-
end
|
20
|
+
report.each do |file, lines|
|
21
|
+
store_map("#{BASE_KEY}.#{file}", lines)
|
34
22
|
end
|
35
23
|
end
|
36
24
|
|
@@ -47,55 +35,27 @@ module Coverband
|
|
47
35
|
end
|
48
36
|
|
49
37
|
def covered_lines_for_file(file)
|
50
|
-
|
51
|
-
@redis.smembers("#{BASE_KEY}.#{file}").map(&:to_i)
|
52
|
-
else
|
53
|
-
@redis.hgetall("#{BASE_KEY}.#{file}")
|
54
|
-
end
|
38
|
+
@redis.hgetall("#{BASE_KEY}.#{file}")
|
55
39
|
end
|
56
40
|
|
57
41
|
private
|
58
42
|
|
59
43
|
attr_reader :redis
|
60
44
|
|
61
|
-
def sadd_supports_array?
|
62
|
-
@_sadd_supports_array
|
63
|
-
end
|
64
|
-
|
65
45
|
def store_map(key, values)
|
66
46
|
unless values.empty?
|
67
47
|
existing = redis.hgetall(key)
|
68
|
-
#in redis all keys are strings
|
69
|
-
values = Hash[values.map{|k,val| [k.to_s,val] }
|
70
|
-
values.merge!(
|
48
|
+
# in redis all keys are strings
|
49
|
+
values = Hash[values.map { |k, val| [k.to_s, val] }]
|
50
|
+
values.merge!(existing) { |_k, old_v, new_v| old_v.to_i + new_v.to_i }
|
71
51
|
redis.mapped_hmset(key, values)
|
72
52
|
end
|
73
53
|
end
|
74
54
|
|
75
55
|
def store_array(key, values)
|
76
|
-
|
77
|
-
redis.sadd(key, values) if (values.length > 0)
|
78
|
-
else
|
79
|
-
values.each do |value|
|
80
|
-
redis.sadd(key, value)
|
81
|
-
end
|
82
|
-
end
|
56
|
+
redis.sadd(key, values) unless values.empty?
|
83
57
|
values
|
84
58
|
end
|
85
|
-
|
86
|
-
def recent_server_version?
|
87
|
-
info_data = redis.info
|
88
|
-
if info_data.is_a?(Hash)
|
89
|
-
Gem::Version.new(info_data['redis_version']) >= Gem::Version.new('2.4')
|
90
|
-
else
|
91
|
-
#guess supported
|
92
|
-
true
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def recent_gem_version?
|
97
|
-
Gem::Version.new(Redis::VERSION) >= Gem::Version.new('3.0')
|
98
|
-
end
|
99
59
|
end
|
100
60
|
end
|
101
61
|
end
|
data/lib/coverband/baseline.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Coverband
|
2
4
|
class Baseline
|
3
|
-
|
4
5
|
def self.record
|
5
6
|
require 'coverage'
|
6
7
|
Coverage.start
|
@@ -8,12 +9,12 @@ module Coverband
|
|
8
9
|
|
9
10
|
project_directory = File.expand_path(Coverband.configuration.root)
|
10
11
|
results = Coverage.result
|
11
|
-
results = results.reject { |key,
|
12
|
+
results = results.reject { |key, _val| !key.match(project_directory) || Coverband.configuration.ignore.any? { |pattern| key.match(/#{pattern}/) } }
|
12
13
|
|
13
14
|
Coverband.configuration.store.save_report(convert_coverage_format(results))
|
14
15
|
end
|
15
16
|
|
16
|
-
def self.parse_baseline(
|
17
|
+
def self.parse_baseline(_back_compat = nil)
|
17
18
|
Coverband.configuration.store.coverage
|
18
19
|
end
|
19
20
|
|
@@ -33,12 +34,11 @@ module Coverband
|
|
33
34
|
results.each_pair do |file, data|
|
34
35
|
lines_map = {}
|
35
36
|
data.each_with_index do |hits, index|
|
36
|
-
lines_map[(index+1)] = hits unless hits.nil?
|
37
|
+
lines_map[(index + 1)] = hits unless hits.nil?
|
37
38
|
end
|
38
39
|
file_map[file] = lines_map
|
39
40
|
end
|
40
41
|
file_map
|
41
42
|
end
|
42
|
-
|
43
43
|
end
|
44
44
|
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Coverband
|
4
|
+
module Collectors
|
5
|
+
class Base
|
6
|
+
def self.instance
|
7
|
+
if Coverband.configuration.collector == 'trace'
|
8
|
+
Thread.current[:coverband_instance] ||= Coverband::Collectors::Trace.new
|
9
|
+
elsif Coverband.configuration.collector == 'coverage'
|
10
|
+
Thread.current[:coverband_instance] ||= Coverband::Collectors::Coverage.new
|
11
|
+
else
|
12
|
+
raise 'select valid collector [trace, coverage]'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def start
|
17
|
+
@enabled = true
|
18
|
+
record_coverage
|
19
|
+
end
|
20
|
+
|
21
|
+
def stop
|
22
|
+
@enabled = false
|
23
|
+
unset_tracer
|
24
|
+
end
|
25
|
+
|
26
|
+
def sample
|
27
|
+
configure_sampling
|
28
|
+
record_coverage
|
29
|
+
result = yield
|
30
|
+
report_coverage
|
31
|
+
result
|
32
|
+
end
|
33
|
+
|
34
|
+
def save
|
35
|
+
@enabled = true
|
36
|
+
report_coverage
|
37
|
+
@enabled = false
|
38
|
+
end
|
39
|
+
|
40
|
+
def reset_instance
|
41
|
+
@project_directory = File.expand_path(Coverband.configuration.root)
|
42
|
+
@enabled = false
|
43
|
+
@disable_on_failure_for = Coverband.configuration.disable_on_failure_for
|
44
|
+
@file_line_usage = {}
|
45
|
+
@ignored_files = Set.new
|
46
|
+
@startup_delay = Coverband.configuration.startup_delay
|
47
|
+
@ignore_patterns = Coverband.configuration.ignore + ['internal:prelude', 'schema.rb']
|
48
|
+
@ignore_patterns += ['gems'] unless Coverband.configuration.include_gems
|
49
|
+
@sample_percentage = Coverband.configuration.percentage
|
50
|
+
@store = Coverband.configuration.store
|
51
|
+
@store = Coverband::Adapters::MemoryCacheStore.new(@store) if Coverband.configuration.memory_caching
|
52
|
+
@stats = Coverband.configuration.stats
|
53
|
+
@verbose = Coverband.configuration.verbose
|
54
|
+
@logger = Coverband.configuration.logger
|
55
|
+
@current_thread = Thread.current
|
56
|
+
Thread.current[:coverband_instance] = nil
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
def configure_sampling
|
61
|
+
if @startup_delay != 0 || (rand * 100.0) > @sample_percentage
|
62
|
+
@startup_delay -= 1 if @startup_delay > 0
|
63
|
+
@enabled = false
|
64
|
+
else
|
65
|
+
@enabled = true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def record_coverage
|
70
|
+
if @enabled && !failed_recently?
|
71
|
+
set_tracer
|
72
|
+
else
|
73
|
+
unset_tracer
|
74
|
+
end
|
75
|
+
# support old ruby before &. safe digging
|
76
|
+
@stats.increment "coverband.request.recorded.#{@enabled}" if @stats
|
77
|
+
rescue RuntimeError => err
|
78
|
+
failed!
|
79
|
+
if @verbose
|
80
|
+
@logger.info 'error stating recording coverage'
|
81
|
+
@logger.info "error: #{err.inspect} #{err.message}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def report_coverage
|
86
|
+
raise 'abstract'
|
87
|
+
end
|
88
|
+
|
89
|
+
protected
|
90
|
+
|
91
|
+
def track_file?(file)
|
92
|
+
@ignore_patterns.none? { |pattern| file.include?(pattern) } && file.start_with?(@project_directory)
|
93
|
+
end
|
94
|
+
|
95
|
+
def set_tracer
|
96
|
+
raise 'abstract'
|
97
|
+
end
|
98
|
+
|
99
|
+
def unset_tracer
|
100
|
+
raise 'abstract'
|
101
|
+
end
|
102
|
+
|
103
|
+
def output_file_line_usage
|
104
|
+
@logger.info 'coverband debug coverband file:line usage:'
|
105
|
+
@file_line_usage.sort_by { |_key, value| value.length }.each do |pair|
|
106
|
+
file = pair.first
|
107
|
+
lines = pair.last
|
108
|
+
@logger.info "file: #{file} => #{lines.sort_by { |_key, value| value }}"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def failed_at_thread_key
|
115
|
+
"__#{self.class.name}__failed_at"
|
116
|
+
end
|
117
|
+
|
118
|
+
def failed_at
|
119
|
+
Thread.current[failed_at_thread_key]
|
120
|
+
end
|
121
|
+
|
122
|
+
def failed_at=(time)
|
123
|
+
Thread.current[failed_at_thread_key] = time
|
124
|
+
end
|
125
|
+
|
126
|
+
def failed!
|
127
|
+
self.failed_at = Time.now
|
128
|
+
end
|
129
|
+
|
130
|
+
def failed_recently?
|
131
|
+
return false unless @disable_on_failure_for && failed_at
|
132
|
+
failed_at + @disable_on_failure_for > Time.now
|
133
|
+
end
|
134
|
+
|
135
|
+
def initialize
|
136
|
+
reset_instance
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|