coverband 4.2.5 → 5.0.0.rc.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/.standard.yml +25 -0
  3. data/.travis.yml +2 -1
  4. data/Gemfile +5 -7
  5. data/Gemfile.rails4 +0 -3
  6. data/Gemfile.rails6 +0 -3
  7. data/README.md +24 -77
  8. data/Rakefile +17 -17
  9. data/changes.md +31 -34
  10. data/config.ru +1 -1
  11. data/coverband.gemspec +30 -34
  12. data/lib/alternative_coverband_patch.rb +5 -0
  13. data/lib/coverband.rb +68 -44
  14. data/lib/coverband/adapters/base.rb +17 -18
  15. data/lib/coverband/adapters/file_store.rb +38 -6
  16. data/lib/coverband/adapters/hash_redis_store.rb +24 -21
  17. data/lib/coverband/adapters/redis_store.rb +12 -12
  18. data/lib/coverband/adapters/stdout_store.rb +41 -0
  19. data/lib/coverband/adapters/web_service_store.rb +157 -0
  20. data/lib/coverband/at_exit.rb +1 -1
  21. data/lib/coverband/collectors/coverage.rb +15 -27
  22. data/lib/coverband/collectors/delta.rb +29 -9
  23. data/lib/coverband/collectors/view_tracker.rb +19 -11
  24. data/lib/coverband/collectors/view_tracker_service.rb +59 -0
  25. data/lib/coverband/configuration.rb +121 -88
  26. data/lib/coverband/integrations/background.rb +6 -6
  27. data/lib/coverband/integrations/rack_server_check.rb +3 -3
  28. data/lib/coverband/integrations/resque.rb +13 -1
  29. data/lib/coverband/reporters/base.rb +10 -10
  30. data/lib/coverband/reporters/console_report.rb +1 -1
  31. data/lib/coverband/reporters/html_report.rb +10 -30
  32. data/lib/coverband/reporters/web.rb +55 -50
  33. data/lib/coverband/utils/absolute_file_converter.rb +6 -6
  34. data/lib/coverband/utils/html_formatter.rb +32 -61
  35. data/lib/coverband/utils/railtie.rb +23 -6
  36. data/lib/coverband/utils/relative_file_converter.rb +2 -2
  37. data/lib/coverband/utils/result.rb +6 -11
  38. data/lib/coverband/utils/results.rb +0 -10
  39. data/lib/coverband/utils/source_file.rb +21 -30
  40. data/lib/coverband/utils/tasks.rb +8 -11
  41. data/lib/coverband/version.rb +1 -1
  42. data/public/application.js +0 -30
  43. data/test/benchmarks/benchmark.rake +97 -92
  44. data/test/benchmarks/dog.rb +1 -1
  45. data/test/benchmarks/init_rails.rake +4 -4
  46. data/test/coverband/adapters/base_test.rb +29 -30
  47. data/test/coverband/adapters/file_store_test.rb +19 -20
  48. data/test/coverband/adapters/hash_redis_store_test.rb +57 -57
  49. data/test/coverband/adapters/redis_store_test.rb +26 -26
  50. data/test/coverband/adapters/web_service_store_test.rb +56 -0
  51. data/test/coverband/at_exit_test.rb +2 -2
  52. data/test/coverband/collectors/coverage_test.rb +33 -47
  53. data/test/coverband/collectors/delta_test.rb +52 -23
  54. data/test/coverband/collectors/view_tracker_test.rb +35 -35
  55. data/test/coverband/configuration_test.rb +27 -53
  56. data/test/coverband/coverband_test.rb +11 -11
  57. data/test/coverband/integrations/background_middleware_test.rb +10 -10
  58. data/test/coverband/integrations/background_test.rb +6 -5
  59. data/test/coverband/integrations/rack_server_check_test.rb +7 -7
  60. data/test/coverband/integrations/report_middleware_test.rb +9 -9
  61. data/test/coverband/integrations/resque_worker_test.rb +9 -9
  62. data/test/coverband/integrations/test_resque_job.rb +1 -1
  63. data/test/coverband/reporters/base_test.rb +9 -9
  64. data/test/coverband/reporters/console_test.rb +6 -6
  65. data/test/coverband/reporters/html_test.rb +36 -48
  66. data/test/coverband/reporters/web_test.rb +16 -18
  67. data/test/coverband/utils/absolute_file_converter_test.rb +22 -22
  68. data/test/coverband/utils/file_hasher_test.rb +6 -12
  69. data/test/coverband/utils/file_list_test.rb +13 -13
  70. data/test/coverband/utils/html_formatter_test.rb +9 -23
  71. data/test/coverband/utils/lines_classifier_test.rb +29 -29
  72. data/test/coverband/utils/relative_file_converter_test.rb +13 -13
  73. data/test/coverband/utils/result_test.rb +18 -18
  74. data/test/coverband/utils/results_test.rb +17 -17
  75. data/test/coverband/utils/source_file_line_test.rb +46 -46
  76. data/test/coverband/utils/source_file_test.rb +38 -88
  77. data/test/dog.rb +1 -1
  78. data/test/fake_app/basic_rack.rb +2 -2
  79. data/test/fixtures/app/controllers/sample_controller.rb +1 -1
  80. data/test/fixtures/app/models/user.rb +1 -1
  81. data/test/fixtures/sample.rb +1 -1
  82. data/test/fixtures/utf-8.rb +0 -2
  83. data/test/forked/rails_full_stack_test.rb +24 -27
  84. data/test/forked/rails_rake_full_stack_test.rb +7 -26
  85. data/test/integration/full_stack_test.rb +11 -22
  86. data/test/jruby_check.rb +2 -3
  87. data/test/rails4_dummy/Rakefile +1 -1
  88. data/test/rails4_dummy/config.ru +1 -1
  89. data/test/rails4_dummy/config/application.rb +4 -4
  90. data/test/rails4_dummy/config/boot.rb +2 -2
  91. data/test/rails4_dummy/config/coverband.rb +1 -1
  92. data/test/rails4_dummy/config/coverband_missing_redis.rb +1 -1
  93. data/test/rails4_dummy/config/environment.rb +1 -1
  94. data/test/rails4_dummy/config/routes.rb +2 -2
  95. data/test/rails5_dummy/Rakefile +1 -1
  96. data/test/rails5_dummy/config.ru +1 -1
  97. data/test/rails5_dummy/config/application.rb +3 -3
  98. data/test/rails5_dummy/config/coverband.rb +8 -8
  99. data/test/rails5_dummy/config/coverband_missing_redis.rb +8 -8
  100. data/test/rails5_dummy/config/environment.rb +1 -1
  101. data/test/rails5_dummy/config/routes.rb +2 -2
  102. data/test/rails6_dummy/Rakefile +1 -1
  103. data/test/rails6_dummy/config.ru +1 -1
  104. data/test/rails6_dummy/config/application.rb +4 -4
  105. data/test/rails6_dummy/config/boot.rb +2 -2
  106. data/test/rails6_dummy/config/coverband.rb +1 -1
  107. data/test/rails6_dummy/config/coverband_missing_redis.rb +1 -1
  108. data/test/rails6_dummy/config/environment.rb +1 -1
  109. data/test/rails6_dummy/config/routes.rb +2 -2
  110. data/test/rails_test_helper.rb +11 -11
  111. data/test/test_helper.rb +43 -34
  112. data/test/unique_files.rb +10 -10
  113. data/views/layout.erb +2 -12
  114. metadata +15 -34
  115. data/.rubocop.yml +0 -84
  116. data/lib/coverband/integrations/bundler.rb +0 -8
  117. data/lib/coverband/utils/file_groups.rb +0 -53
  118. data/lib/coverband/utils/gem_list.rb +0 -31
  119. data/lib/coverband/utils/s3_report.rb +0 -105
  120. data/test/coverband/utils/file_groups_test.rb +0 -61
  121. data/test/coverband/utils/gem_list_test.rb +0 -48
  122. data/test/coverband/utils/s3_report_test.rb +0 -44
  123. data/views/gem_list.erb +0 -63
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coverband
4
+ module Adapters
5
+ ###
6
+ # StdoutStore is for testing and development
7
+ #
8
+ # Usage:
9
+ # config.store = Coverband::Adapters::StdoutStore.new
10
+ ###
11
+ class StdoutStore < Base
12
+ def initialize(_opts = {})
13
+ super()
14
+ end
15
+
16
+ def clear!
17
+ # NOOP
18
+ end
19
+
20
+ def size
21
+ 0
22
+ end
23
+
24
+ def migrate!
25
+ raise NotImplementedError, "StdoutStore doesn't support migrations"
26
+ end
27
+
28
+ def coverage(_local_type = nil)
29
+ {}
30
+ end
31
+
32
+ def save_report(report)
33
+ $stdout.puts(report.to_json)
34
+ end
35
+
36
+ def raw_store
37
+ raise NotImplementedError, "StdoutStore doesn't support raw_store"
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,157 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coverband
4
+ module Adapters
5
+ ###
6
+ # WebServiceStore store a merged coverage file to local disk
7
+ # TODO: add webmock tests
8
+ ###
9
+ class WebServiceStore < Base
10
+ attr_reader :coverband_url, :process_type, :runtime_env, :hostname, :pid
11
+
12
+ def initialize(coverband_url, opts = {})
13
+ super()
14
+ require "socket"
15
+ require "securerandom"
16
+ @coverband_url = coverband_url
17
+ @process_type = opts.fetch(:process_type) { $PROGRAM_NAME&.split("/")&.last || Coverband.configuration.process_type }
18
+ @hostname = opts.fetch(:hostname) { ENV["DYNO"] || Socket.gethostname.force_encoding("utf-8").encode }
19
+ @hostname = @hostname.delete("'", "").delete("’", "")
20
+ @runtime_env = opts.fetch(:runtime_env) { Coverband.configuration.coverband_env }
21
+ @failed_coverage_reports = []
22
+ end
23
+
24
+ def logger
25
+ Coverband.configuration.logger
26
+ end
27
+
28
+ def clear!
29
+ # done via service UI
30
+ raise "not supported via service"
31
+ end
32
+
33
+ def clear_file!(filename)
34
+ # done via service UI
35
+ raise "not supported via service"
36
+ end
37
+
38
+ # NOTE: Should support nil to mean not supported
39
+ # the size feature doesn't really makde sense for the service
40
+ def size
41
+ 0
42
+ end
43
+
44
+ ###
45
+ # Fetch coverband coverage via the API
46
+ # This would allow one to expore from the service and move back to the open source
47
+ # without having to reset coverage
48
+ ###
49
+ def coverage(local_type = nil, opts = {})
50
+ return if Coverband.configuration.service_disabled_dev_test_env?
51
+
52
+ local_type ||= opts.key?(:override_type) ? opts[:override_type] : type
53
+ env_filter = opts.key?(:env_filter) ? opts[:env_filter] : "production"
54
+ uri = URI("#{coverband_url}/api/coverage?type=#{local_type}&env_filter=#{env_filter}")
55
+ req = Net::HTTP::Get.new(uri, "Content-Type" => "application/json", "Coverband-Token" => Coverband.configuration.api_key)
56
+ res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
57
+ http.request(req)
58
+ end
59
+ coverage_data = JSON.parse(res.body)
60
+ coverage_data
61
+ rescue => e
62
+ logger&.error "Coverband: Error while retrieving coverage #{e}" if Coverband.configuration.verbose || Coverband.configuration.service_dev_mode
63
+ end
64
+
65
+ def save_report(report)
66
+ return if report.empty?
67
+
68
+ # We set here vs initialize to avoid setting on the primary process vs child processes
69
+ @pid ||= ::Process.pid
70
+
71
+ # TODO: do we need dup
72
+ # TODO: we don't need upstream timestamps, server will track first_seen
73
+ Thread.new do
74
+ data = expand_report(report.dup)
75
+ full_package = {
76
+ collection_type: "coverage_delta",
77
+ collection_data: {
78
+ tags: {
79
+ process_type: process_type,
80
+ app_loading: type == Coverband::EAGER_TYPE,
81
+ runtime_env: runtime_env,
82
+ pid: pid,
83
+ hostname: hostname
84
+ },
85
+ file_coverage: data
86
+ }
87
+ }
88
+
89
+ save_coverage(full_package)
90
+ retry_failed_reports
91
+ end&.join
92
+ end
93
+
94
+ def raw_store
95
+ raise "not supported via service"
96
+ end
97
+
98
+ private
99
+
100
+ def retry_failed_reports
101
+ retries = []
102
+ @failed_coverage_reports.any? do
103
+ begin
104
+ report_body = @failed_coverage_reports.pop
105
+ send_report_body(report_body)
106
+ rescue
107
+ retries << report_body
108
+ end
109
+ end
110
+ retries.each do |report_body|
111
+ add_retry_message(report_body)
112
+ end
113
+ end
114
+
115
+ def add_retry_message(report_body)
116
+ if @failed_coverage_reports.length > 5
117
+ logger&.info "Coverband: The errored reporting queue has reached 5. Subsequent reports will not be transmitted"
118
+ else
119
+ @failed_coverage_reports << report_body
120
+ end
121
+ end
122
+
123
+ def save_coverage(data)
124
+ if Coverband.configuration.api_key.nil?
125
+ puts "Coverband: Error: no Coverband API key was found!"
126
+ return
127
+ end
128
+
129
+ coverage_body = {remote_uuid: SecureRandom.uuid, data: data}.to_json
130
+ send_report_body(coverage_body)
131
+ rescue => e
132
+ add_retry_message(coverage_body)
133
+ logger&.info "Coverband: Error while saving coverage #{e}" if Coverband.configuration.verbose || Coverband.configuration.service_dev_mode
134
+ end
135
+
136
+ def send_report_body(coverage_body)
137
+ uri = URI("#{coverband_url}/api/collector")
138
+ req = ::Net::HTTP::Post.new(uri, "Content-Type" => "application/json", "Coverband-Token" => Coverband.configuration.api_key)
139
+ req.body = coverage_body
140
+ logger&.info "Coverband: saving (#{uri}) #{req.body}" if Coverband.configuration.verbose
141
+ res = ::Net::HTTP.start(
142
+ uri.hostname,
143
+ uri.port,
144
+ open_timeout: Coverband.configuration.coverband_timeout,
145
+ read_timeout: Coverband.configuration.coverband_timeout,
146
+ ssl_timeout: Coverband.configuration.coverband_timeout,
147
+ use_ssl: uri.scheme == "https"
148
+ ) do |http|
149
+ http.request(req)
150
+ end
151
+ if res.code.to_i >= 500
152
+ add_retry_message(coverage_body)
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
@@ -6,7 +6,7 @@ module Coverband
6
6
 
7
7
  @at_exit_registered = nil
8
8
  def self.register
9
- return if ENV['COVERBAND_DISABLE_AT_EXIT']
9
+ return if ENV["COVERBAND_DISABLE_AT_EXIT"]
10
10
  return if @at_exit_registered
11
11
 
12
12
  @semaphore.synchronize do
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'singleton'
4
- require_relative 'delta'
3
+ require "singleton"
4
+ require_relative "delta"
5
5
 
6
6
  module Coverband
7
7
  module Collectors
@@ -25,7 +25,6 @@ module Coverband
25
25
  @verbose = Coverband.configuration.verbose
26
26
  @logger = Coverband.configuration.logger
27
27
  @test_env = Coverband.configuration.test_env
28
- @track_gems = Coverband.configuration.track_gems
29
28
  Delta.reset
30
29
  self
31
30
  end
@@ -49,53 +48,42 @@ module Coverband
49
48
 
50
49
  def report_coverage
51
50
  @semaphore.synchronize do
52
- raise 'no Coverband store set' unless @store
51
+ raise "no Coverband store set" unless @store
53
52
 
54
53
  files_with_line_usage = filtered_files(Delta.results)
55
54
  @store.save_report(files_with_line_usage)
56
55
  end
57
- rescue StandardError => e
58
- @logger&.error 'coverage failed to store'
56
+ rescue => e
57
+ @logger&.error "coverage failed to store"
59
58
  @logger&.error "Coverband Error: #{e.inspect} #{e.message}"
60
59
  e.backtrace.each { |line| @logger&.error line } if @verbose
61
60
  raise e if @test_env
62
61
  end
63
62
 
64
- protected
65
-
66
- ###
67
- # Normally I would break this out into additional methods
68
- # and improve the readability but this is in a tight loop
69
- # on the critical performance path, and any refactoring I come up with
70
- # would slow down the performance.
71
- ###
72
- def track_file?(file)
73
- @ignore_patterns.none? do |pattern|
74
- file.match(pattern)
75
- end && (file.start_with?(@project_directory) ||
76
- (@track_gems &&
77
- Coverband.configuration.gem_paths.any? { |path| file.start_with?(path) }))
78
- end
79
-
80
63
  private
81
64
 
82
65
  def filtered_files(new_results)
83
- new_results.select! { |file, coverage| track_file?(file) && coverage.any? { |value| value&.nonzero? } }
66
+ new_results.select! { |_file, coverage| coverage.any? { |value| value&.nonzero? } }
84
67
  new_results
85
68
  end
86
69
 
87
70
  def initialize
88
71
  @semaphore = Mutex.new
89
- raise NotImplementedError, 'Coverage needs Ruby > 2.3.0' if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.3.0')
72
+ raise NotImplementedError, "Coverage needs Ruby > 2.3.0" if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.3.0")
90
73
 
91
- require 'coverage'
74
+ require "coverage"
75
+ if RUBY_PLATFORM == "java"
76
+ unless ::Coverage.respond_to?(:line_stub)
77
+ require "coverband/utils/jruby_ext"
78
+ end
79
+ end
92
80
  if defined?(SimpleCov) && defined?(Rails) && defined?(Rails.env) && Rails.env.test?
93
81
  puts "Coverband: detected SimpleCov in test Env, allowing it to start Coverage"
94
82
  puts "Coverband: to ensure no error logs or missing Coverage call `SimpleCov.start` prior to requiring Coverband"
95
83
  else
96
- if Coverage.ruby_version_greater_than_or_equal_to?('2.6.0')
84
+ if Coverage.ruby_version_greater_than_or_equal_to?("2.6.0")
97
85
  ::Coverage.start(oneshot_lines: Coverband.configuration.use_oneshot_lines_coverage) unless ::Coverage.running?
98
- elsif Coverage.ruby_version_greater_than_or_equal_to?('2.5.0')
86
+ elsif Coverage.ruby_version_greater_than_or_equal_to?("2.5.0")
99
87
  ::Coverage.start unless ::Coverage.running?
100
88
  else
101
89
  ::Coverage.start
@@ -39,23 +39,33 @@ module Coverband
39
39
 
40
40
  def self.reset
41
41
  @@previous_coverage = {}
42
+ @@project_directory = File.expand_path(Coverband.configuration.root)
43
+ @@ignore_patterns = Coverband.configuration.ignore
42
44
  end
43
45
 
44
46
  private
45
47
 
46
48
  def generate
47
- # TODO: if we filtered before doing this we would avoid calculating the line diff on a ton of files
48
- # This would be a fairly noticeable perf win
49
49
  current_coverage.each_with_object({}) do |(file, line_counts), new_results|
50
+ ###
51
+ # Eager filter:
52
+ # Normally I would break this out into additional methods
53
+ # and improve the readability but this is in a tight loop
54
+ # on the critical performance path, and any refactoring I come up with
55
+ # would slow down the performance.
56
+ ###
57
+ next unless @@ignore_patterns.none? { |pattern| file.match(pattern) } &&
58
+ file.start_with?(@@project_directory)
59
+
50
60
  # This handles Coverage branch support, setup by default in
51
61
  # simplecov 0.18.x
52
62
  arr_line_counts = line_counts.is_a?(Hash) ? line_counts[:lines] : line_counts
53
63
  new_results[file] = if @@previous_coverage && @@previous_coverage[file]
54
- prev_line_counts = @@previous_coverage[file].is_a?(Hash) ? @@previous_coverage[file][:lines] : @@previous_coverage[file]
55
- array_diff(arr_line_counts, prev_line_counts)
56
- else
57
- arr_line_counts
58
- end
64
+ prev_line_counts = @@previous_coverage[file].is_a?(Hash) ? @@previous_coverage[file][:lines] : @@previous_coverage[file]
65
+ array_diff(arr_line_counts, prev_line_counts)
66
+ else
67
+ arr_line_counts
68
+ end
59
69
  end
60
70
  end
61
71
 
@@ -67,10 +77,20 @@ module Coverband
67
77
 
68
78
  def transform_oneshot_lines_results(results)
69
79
  results.each_with_object({}) do |(file, coverage), new_results|
80
+ ###
81
+ # Eager filter:
82
+ # Normally I would break this out into additional methods
83
+ # and improve the readability but this is in a tight loop
84
+ # on the critical performance path, and any refactoring I come up with
85
+ # would slow down the performance.
86
+ ###
87
+ next unless @@ignore_patterns.none? { |pattern| file.match(pattern) } &&
88
+ file.start_with?(@@project_directory)
89
+
70
90
  @@stubs[file] ||= ::Coverage.line_stub(file)
71
- transformed_line_counts = coverage[:oneshot_lines].each_with_object(@@stubs[file].dup) do |line_number, line_counts|
91
+ transformed_line_counts = coverage[:oneshot_lines].each_with_object(@@stubs[file].dup) { |line_number, line_counts|
72
92
  line_counts[line_number - 1] = 1
73
- end
93
+ }
74
94
  new_results[file] = transformed_line_counts
75
95
  end
76
96
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'singleton'
3
+ require "singleton"
4
4
 
5
5
  module Coverband
6
6
  module Collectors
@@ -14,12 +14,12 @@ module Coverband
14
14
  # TODO: test and ensure slim, haml, and other support
15
15
  ###
16
16
  class ViewTracker
17
- DEFAULT_TARGET = Dir.glob('app/views/**/*.html.erb').reject { |file| file.match(/(_mailer)/) }
17
+ DEFAULT_TARGET = Dir.glob("app/views/**/*.html.erb").reject { |file| file.match(/(_mailer)/) }
18
18
  attr_accessor :target, :logged_views, :views_to_record
19
19
  attr_reader :logger, :roots, :store, :ignore_patterns
20
20
 
21
21
  def initialize(options = {})
22
- raise NotImplementedError, 'View Tracker requires Rails 4 or greater' unless self.class.supported_version?
22
+ raise NotImplementedError, "View Tracker requires Rails 4 or greater" unless self.class.supported_version?
23
23
 
24
24
  @project_directory = File.expand_path(Coverband.configuration.root)
25
25
  @ignore_patterns = Coverband.configuration.ignore
@@ -28,7 +28,7 @@ module Coverband
28
28
  @target = options.fetch(:target) { DEFAULT_TARGET }
29
29
 
30
30
  @roots = options.fetch(:roots) { Coverband.configuration.all_root_patterns }
31
- @roots = @roots.split(',') if @roots.is_a?(String)
31
+ @roots = @roots.split(",") if @roots.is_a?(String)
32
32
  @one_time_timestamp = false
33
33
 
34
34
  @logged_views = []
@@ -65,7 +65,7 @@ module Coverband
65
65
  normalized_views = {}
66
66
  views.each_pair do |view, time|
67
67
  roots.each do |root|
68
- view = view.gsub(/#{root}/, '')
68
+ view = view.gsub(/#{root}/, "")
69
69
  end
70
70
  normalized_views[view] = time
71
71
  end
@@ -90,7 +90,7 @@ module Coverband
90
90
  if (tracking_time = redis_store.get(tracker_time_key))
91
91
  Time.at(tracking_time.to_i).iso8601
92
92
  else
93
- 'N/A'
93
+ "N/A"
94
94
  end
95
95
  end
96
96
 
@@ -108,21 +108,21 @@ module Coverband
108
108
  end
109
109
 
110
110
  def report_views_tracked
111
- redis_store.set(tracker_time_key, Time.now.to_i) unless @one_time_timestamp || redis_store.exists(tracker_time_key)
111
+ redis_store.set(tracker_time_key, Time.now.to_i) unless @one_time_timestamp || tracker_time_key_exists?
112
112
  @one_time_timestamp = true
113
113
  reported_time = Time.now.to_i
114
114
  views_to_record.each do |file|
115
115
  redis_store.hset(tracker_key, file, reported_time)
116
116
  end
117
117
  self.views_to_record = []
118
- rescue StandardError => e
118
+ rescue => e
119
119
  # we don't want to raise errors if Coverband can't reach redis.
120
120
  # This is a nice to have not a bring the system down
121
121
  logger&.error "Coverband: view_tracker failed to store, error #{e.class.name}"
122
122
  end
123
123
 
124
124
  def self.supported_version?
125
- defined?(Rails) && defined?(Rails::VERSION) && Rails::VERSION::STRING.split('.').first.to_i >= 4
125
+ defined?(Rails) && defined?(Rails::VERSION) && Rails::VERSION::STRING.split(".").first.to_i >= 4
126
126
  end
127
127
 
128
128
  protected
@@ -145,12 +145,20 @@ module Coverband
145
145
  store.raw_store
146
146
  end
147
147
 
148
+ def tracker_time_key_exists?
149
+ if defined?(redis_store.exists?)
150
+ redis_store.exists?(tracker_time_key)
151
+ else
152
+ redis_store.exists(tracker_time_key)
153
+ end
154
+ end
155
+
148
156
  def tracker_key
149
- 'render_tracker_2'
157
+ "render_tracker_2"
150
158
  end
151
159
 
152
160
  def tracker_time_key
153
- 'render_tracker_time'
161
+ "render_tracker_time"
154
162
  end
155
163
  end
156
164
  end