qa_server 6.2.0 → 7.0.0

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.
Files changed (24) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/app/cache_processors/concerns/qa_server/cache_keys.rb +15 -0
  4. data/app/cache_processors/qa_server/cache_expiry_service.rb +33 -0
  5. data/app/cache_processors/qa_server/performance_daily_graph_cache.rb +60 -0
  6. data/app/cache_processors/qa_server/performance_datatable_cache.rb +33 -0
  7. data/app/cache_processors/qa_server/performance_hourly_graph_cache.rb +65 -0
  8. data/app/cache_processors/qa_server/performance_monthly_graph_cache.rb +60 -0
  9. data/app/cache_processors/qa_server/scenario_history_cache.rb +35 -0
  10. data/app/cache_processors/qa_server/scenario_run_cache.rb +28 -0
  11. data/app/cache_processors/qa_server/scenario_run_failures_cache.rb +51 -0
  12. data/app/cache_processors/qa_server/scenario_run_summary_cache.rb +40 -0
  13. data/app/controllers/qa_server/monitor_status_controller.rb +39 -48
  14. data/app/jobs/qa_server/monitor_tests_job.rb +1 -1
  15. data/app/models/qa_server/scenario_run_history.rb +27 -84
  16. data/app/models/qa_server/scenario_run_registry.rb +1 -1
  17. data/app/services/qa_server/performance_datatable_service.rb +6 -9
  18. data/app/services/qa_server/performance_graph_data_service.rb +77 -154
  19. data/app/services/qa_server/performance_graphing_service.rb +34 -47
  20. data/lib/qa_server/version.rb +1 -1
  21. data/spec/{services/qa_server/monitor_cache_service_spec.rb → cache_processors/qa_server/cache_expiry_service_spec.rb} +1 -1
  22. metadata +15 -6
  23. data/app/services/qa_server/monitor_cache_service.rb +0 -22
  24. /data/app/{models → cache_processors}/qa_server/performance_cache.rb +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b602ac44639871d5021eb47493edf93fb8abdc25
4
- data.tar.gz: bf9e6a5ece3786edab98ed79d1fc3edb8e54f8b7
3
+ metadata.gz: fb73032a8e4f6dfb0d782a8635d8f43668b63a06
4
+ data.tar.gz: a857cd62d41bc035a241419815e9fff67fdf1d5a
5
5
  SHA512:
6
- metadata.gz: ec1fec69f78b763fc7012c92118fddeb6e0f6ad98d53d9ae80d959f80f0c1373c435626452644294ecbcf1b1843ac37517af58a71e04ece333a9d14afa99486f
7
- data.tar.gz: d4e87a9c8157f8d03b3fdbc26ded7698f294cee41f9c7a2222355db878c26ab7e7d121d32dda69fbf1660f5b7942de7ec05688431a364b1e06f22b9b73967598
6
+ metadata.gz: 490cfcc14713a0fad8e3d5d60aa5d23a5699c5c3ab23359164848a8f5a3223bbf8fb2bbbffbd9f59b5220efed3eec4f4d63a8fece546dee916886f91a51f0287
7
+ data.tar.gz: '04027957aeb5955a65a4a5d23d4fd11c7b98827c650ba9b736512953fb10c260e11c9ad4f76de85991861706874eedd7e04bb523184c2a1693e079dc0317b142'
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ ### 7.0.0 (2020-02-19)
2
+
3
+ * refactor of caching system to simplify the process
4
+ * rename monitor_cache_service to cache_expiry_service
5
+ * move generation of hourly graph to cache_processors
6
+ * move generation of daily and monthly graphs to cache_processors
7
+ * move performance datatable cache control to cache_processors
8
+ * move caching of summary and historical data to cache_processors
9
+ * move caching of test execution marker to cache_processors
10
+ * move performance cache of performance data to cache_processors
11
+
1
12
  ### 6.2.0 (2020-02-17)
2
13
 
3
14
  * use authentication for refreshing monitor tests
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ # This module sets up the keys used to identify data in Rails.cache
3
+ module QaServer
4
+ module CacheKeys
5
+ SCENARIO_RUN_TEST_DATA_CACHE_KEY = "QaServer--CacheKeys--scenario_run_test_data"
6
+ SCENARIO_RUN_SUMMARY_DATA_CACHE_KEY = "QaServer--CacheKeys--scenario_run_summary_data"
7
+ SCENARIO_RUN_FAILURE_DATA_CACHE_KEY = "QaServer--CacheKeys--scenario_run_failure_data"
8
+ SCENARIO_RUN_HISTORY_DATA_CACHE_KEY = "QaServer--CacheKeys--scenario_run_history_data"
9
+
10
+ PERFORMANCE_DATATABLE_DATA_CACHE_KEY = "QaServer--Cache--performance_datatable_data"
11
+ PERFORMANCE_GRAPH_HOURLY_DATA_CACHE_KEY = "QaServer--CacheKeys--performance_graph_hourly_data"
12
+ PERFORMANCE_GRAPH_DAILY_DATA_CACHE_KEY = "QaServer--CacheKeys--performance_graph_daily_data"
13
+ PERFORMANCE_GRAPH_MONTHLY_DATA_CACHE_KEY = "QaServer--CacheKeys--performance_graph_monthly_data"
14
+ end
15
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ # Helper methods for caching for monitoring status.
3
+ module QaServer
4
+ class CacheExpiryService
5
+ class << self
6
+ # @return [Float] number of seconds until cache should expire
7
+ def cache_expiry
8
+ cache_expires_at - QaServer::TimeService.current_time
9
+ end
10
+
11
+ # @param key [String] cache key
12
+ # @param force [Boolean] if true, forces cache to regenerate by returning true; otherwise, uses cache expiry to determine whether cache has expired
13
+ # @return [Boolean] true if cache has expired or is being forced to expire
14
+ def cache_expired?(key:, force:, next_expiry:)
15
+ # will return true only if the full expiry has passed or force was requested
16
+ force = Rails.cache.fetch(key, expires_in: 5.minutes, race_condition_ttl: 30.seconds, force: force) { true }
17
+ # reset cache so it will next expired at expected time
18
+ Rails.cache.fetch(key, expires_in: next_expiry, race_condition_ttl: 30.seconds, force: true) { false }
19
+ force
20
+ end
21
+
22
+ private
23
+
24
+ # @return [ActiveSupport::TimeWithZone] DateTime at which cache should expire
25
+ def cache_expires_at
26
+ offset = QaServer.config.hour_offset_to_expire_cache
27
+ offset_time = QaServer::TimeService.current_time
28
+ offset_time = offset_time.tomorrow unless (offset_time + 5.minutes).hour < offset
29
+ offset_time.beginning_of_day + offset.hours - 5.minutes
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+ # Generate graphs for the past 30 days using cached data. Graphs are generated only if the cache has expired.
3
+ module QaServer
4
+ class PerformanceDailyGraphCache
5
+ class_attribute :authority_list_class, :graph_data_service, :graphing_service
6
+ self.authority_list_class = QaServer::AuthorityListerService
7
+ self.graph_data_service = QaServer::PerformanceGraphDataService
8
+ self.graphing_service = QaServer::PerformanceGraphingService
9
+
10
+ class << self
11
+ include QaServer::CacheKeys
12
+ include QaServer::PerformanceHistoryDataKeys
13
+
14
+ # Generates graphs for the past 30 days for :search, :fetch, and :all actions for each authority.
15
+ # @param force [Boolean] if true, run the tests even if the cache hasn't expired; otherwise, use cache if not expired
16
+ def generate_graphs(force: false)
17
+ return unless QaServer::CacheExpiryService.cache_expired?(key: cache_key_for_force, force: force, next_expiry: next_expiry)
18
+ QaServer.config.monitor_logger.debug("(QaServer::PerformanceDailyGraphCache) - GENERATING daily performance graphs (force: #{force})")
19
+ generate_graphs_for_authorities
20
+ end
21
+
22
+ private
23
+
24
+ def generate_graphs_for_authorities
25
+ auths = authority_list_class.authorities_list
26
+ generate_graphs_for_authority(authority_name: ALL_AUTH) # generates graph for all authorities
27
+ auths.each { |authname| generate_graphs_for_authority(authority_name: authname) }
28
+ end
29
+
30
+ def generate_graphs_for_authority(authority_name:)
31
+ [SEARCH, FETCH, ALL_ACTIONS].each_with_object({}) do |action, hash|
32
+ hash[action] = generate_30_day_graph(authority_name: authority_name, action: action)
33
+ end
34
+ end
35
+
36
+ def generate_30_day_graph(authority_name:, action:)
37
+ # real expiration or force caught by cache_expired? So if we are here, either the cache has expired
38
+ # or force was requested. We still expire the cache and use ttl to catch race conditions.
39
+ Rails.cache.fetch(cache_key_for_authority_action(authority_name: authority_name, action: action),
40
+ expires_in: next_expiry, race_condition_ttl: 1.hour, force: true) do
41
+ data = graph_data_service.calculate_last_30_days(authority_name: authority_name, action: action)
42
+ graphing_service.generate_daily_graph(authority_name: authority_name, action: action, data: data)
43
+ data
44
+ end
45
+ end
46
+
47
+ def cache_key_for_authority_action(authority_name:, action:)
48
+ "#{PERFORMANCE_GRAPH_DAILY_DATA_CACHE_KEY}--#{authority_name}--#{action}"
49
+ end
50
+
51
+ def cache_key_for_force
52
+ "#{PERFORMANCE_GRAPH_DAILY_DATA_CACHE_KEY}--force"
53
+ end
54
+
55
+ def next_expiry
56
+ QaServer::CacheExpiryService.cache_expiry
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ # Maintain a cache of data for the Performance Datatable
3
+ module QaServer
4
+ class PerformanceDatatableCache
5
+ include QaServer::CacheKeys
6
+
7
+ class_attribute :performance_data_service
8
+ self.performance_data_service = QaServer::PerformanceDatatableService
9
+
10
+ # Retrieve performance datatable data from the cache
11
+ # @param force [Boolean] if true, calculate the stats even if the cache hasn't expired; otherwise, use cache if not expired
12
+ # @returns [Hash] performance statistics for configured time period by action for each authority
13
+ # @example
14
+ # { all_authorities:
15
+ # { search:
16
+ # { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5,
17
+ # retrieve_10th_ms: 12.3, graph_load_10th_ms: 12.3, normalization_10th_ms: 4.2, full_request_10th_ms: 16.5,
18
+ # retrieve_90th_ms: 12.3, graph_load_90th_ms: 12.3, normalization_90th_ms: 4.2, full_request_90th_ms: 16.5 },
19
+ # fetch: { ... # same data as for search_stats },
20
+ # all: { ... # same data as for search_stats }
21
+ # },
22
+ # AGROVOC_LD4L_CACHE: { ... # same data for each authority }
23
+ # }
24
+ def self.data(force: false)
25
+ Rails.cache.fetch(PERFORMANCE_DATATABLE_DATA_CACHE_KEY,
26
+ expires_in: QaServer::CacheExpiryService.cache_expiry,
27
+ race_condition_ttl: 5.minutes, force: force) do
28
+ QaServer.config.monitor_logger.debug("(QaServer::PerformanceDatatableCache) - CALCULATING performance datatable stats (force: #{force})")
29
+ performance_data_service.calculate_datatable_data
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+ # Generate graphs for the past 24 hours using cached data. The last hour of data is always calculated and all graphs
3
+ # for are generated.
4
+ module QaServer
5
+ class PerformanceHourlyGraphCache
6
+ class_attribute :authority_list_class, :graph_data_service, :graphing_service
7
+ self.authority_list_class = QaServer::AuthorityListerService
8
+ self.graph_data_service = QaServer::PerformanceGraphDataService
9
+ self.graphing_service = QaServer::PerformanceGraphingService
10
+
11
+ class << self
12
+ include QaServer::CacheKeys
13
+ include QaServer::PerformanceHistoryDataKeys
14
+
15
+ # Generates graphs for the past 24 hours for :search, :fetch, and :all actions for each authority.
16
+ # @param force [Boolean] if true, run the tests even if the cache hasn't expired; otherwise, use cache if not expired
17
+ def generate_graphs(force: false)
18
+ QaServer.config.monitor_logger.debug("(QaServer::PerformanceHourlyGraphCache) - GENERATING hourly performance graphs (force: #{force})")
19
+ QaServer.config.performance_cache.write_all
20
+ generate_graphs_for_authorities(force: force)
21
+ end
22
+
23
+ private
24
+
25
+ def generate_graphs_for_authorities(force:)
26
+ auths = authority_list_class.authorities_list
27
+ generate_graphs_for_authority(authority_name: ALL_AUTH, force: force) # generates graph for all authorities
28
+ auths.each { |authname| generate_graphs_for_authority(authority_name: authname, force: force) }
29
+ end
30
+
31
+ def generate_graphs_for_authority(authority_name:, force:)
32
+ [SEARCH, FETCH, ALL_ACTIONS].each_with_object({}) do |action, hash|
33
+ hash[action] = generate_24_hour_graph(authority_name: authority_name, action: action, force: force)
34
+ end
35
+ end
36
+
37
+ def generate_24_hour_graph(authority_name:, action:, force:)
38
+ graph_created = false
39
+ data = Rails.cache.fetch(cache_key_for_authority_action(authority_name: authority_name, action: action),
40
+ expires_in: QaServer::TimeService.current_time.end_of_hour - QaServer::TimeService.current_time,
41
+ race_condition_ttl: 1.hour, force: force) do
42
+ data = graph_data_service.calculate_last_24_hours(authority_name: authority_name, action: action)
43
+ graphing_service.generate_hourly_graph(authority_name: authority_name, action: action, data: data)
44
+ graph_created = true
45
+ data
46
+ end
47
+ regen_last_hour_and_graph(authority_name: authority_name, action: action, data: data) unless graph_created
48
+ end
49
+
50
+ def regen_last_hour_and_graph(authority_name:, action:, data:)
51
+ Rails.cache.fetch(cache_key_for_authority_action(authority_name: authority_name, action: action),
52
+ expires_in: QaServer::TimeService.current_time.end_of_hour - QaServer::TimeService.current_time,
53
+ race_condition_ttl: 1.hour, force: true) do
54
+ data = graph_data_service.recalculate_last_hour(authority_name: authority_name, action: action, averages: data)
55
+ graphing_service.generate_hourly_graph(authority_name: authority_name, action: action, data: data)
56
+ data
57
+ end
58
+ end
59
+
60
+ def cache_key_for_authority_action(authority_name:, action:)
61
+ "#{PERFORMANCE_GRAPH_HOURLY_DATA_CACHE_KEY}--#{authority_name}--#{action}"
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+ # Generate graphs for the past 12 months using cached data. Graphs are generated only if the cache has expired.
3
+ module QaServer
4
+ class PerformanceMonthlyGraphCache
5
+ class_attribute :authority_list_class, :graph_data_service, :graphing_service
6
+ self.authority_list_class = QaServer::AuthorityListerService
7
+ self.graph_data_service = QaServer::PerformanceGraphDataService
8
+ self.graphing_service = QaServer::PerformanceGraphingService
9
+
10
+ class << self
11
+ include QaServer::CacheKeys
12
+ include QaServer::PerformanceHistoryDataKeys
13
+
14
+ # Generates graphs for the past 30 days for :search, :fetch, and :all actions for each authority.
15
+ # @param force [Boolean] if true, run the tests even if the cache hasn't expired; otherwise, use cache if not expired
16
+ def generate_graphs(force: false)
17
+ return unless QaServer::CacheExpiryService.cache_expired?(key: cache_key_for_force, force: force, next_expiry: next_expiry)
18
+ QaServer.config.monitor_logger.debug("(QaServer::PerformanceMonthlyGraphCache) - GENERATING monthly performance graphs (force: #{force})")
19
+ generate_graphs_for_authorities
20
+ end
21
+
22
+ private
23
+
24
+ def generate_graphs_for_authorities
25
+ auths = authority_list_class.authorities_list
26
+ generate_graphs_for_authority(authority_name: ALL_AUTH) # generates graph for all authorities
27
+ auths.each { |authname| generate_graphs_for_authority(authority_name: authname) }
28
+ end
29
+
30
+ def generate_graphs_for_authority(authority_name:)
31
+ [SEARCH, FETCH, ALL_ACTIONS].each_with_object({}) do |action, hash|
32
+ hash[action] = generate_12_month_graph(authority_name: authority_name, action: action)
33
+ end
34
+ end
35
+
36
+ def generate_12_month_graph(authority_name:, action:)
37
+ # real expiration or force caught by cache_expired? So if we are here, either the cache has expired
38
+ # or force was requested. We still expire the cache and use ttl to catch race conditions.
39
+ Rails.cache.fetch(cache_key_for_authority_action(authority_name: authority_name, action: action),
40
+ expires_in: next_expiry, race_condition_ttl: 1.hour, force: true) do
41
+ data = graph_data_service.calculate_last_12_months(authority_name: authority_name, action: action)
42
+ graphing_service.generate_monthly_graph(authority_name: authority_name, action: action, data: data)
43
+ data
44
+ end
45
+ end
46
+
47
+ def cache_key_for_authority_action(authority_name:, action:)
48
+ "#{PERFORMANCE_GRAPH_MONTHLY_DATA_CACHE_KEY}--#{authority_name}--#{action}"
49
+ end
50
+
51
+ def cache_key_for_force
52
+ "#{PERFORMANCE_GRAPH_MONTHLY_DATA_CACHE_KEY}--force"
53
+ end
54
+
55
+ def next_expiry
56
+ QaServer::CacheExpiryService.cache_expiry
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+ # Maintain a cache of data for Authority Connection History table displayed on Monitor Status page
3
+ module QaServer
4
+ class ScenarioHistoryCache
5
+ class_attribute :scenario_history_class
6
+ self.scenario_history_class = QaServer::ScenarioRunHistory
7
+
8
+ class << self
9
+ include QaServer::CacheKeys
10
+
11
+ # Get a summary of the number of days passing/failing for scenario runs during configured time period
12
+ # @param force [Boolean] if true, run the tests even if the cache hasn't expired; otherwise, use cache if not expired
13
+ # @returns [Array<Hash>] count of days with passing/failing tests for each authority
14
+ # @example [auth_name, failing, passing]
15
+ # { 'agrovoc' => { good: 31, bad: 2 },
16
+ # 'geonames_ld4l_cache' => { good: 32, bad: 1 } }
17
+ def historical_summary(force: false)
18
+ Rails.cache.fetch(cache_key_for_historical_data, expires_in: next_expiry, race_condition_ttl: 30.seconds, force: force) do
19
+ QaServer.config.monitor_logger.debug("(QaServer::ScenarioHistoryCache) - CALCULATING HISTORY of scenario runs (force: force)")
20
+ scenario_history_class.historical_summary
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def cache_key_for_historical_data
27
+ SCENARIO_RUN_HISTORY_DATA_CACHE_KEY
28
+ end
29
+
30
+ def next_expiry
31
+ QaServer::CacheExpiryService.cache_expiry
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ # Maintain a cache controlling the execution of scenario tests.
3
+ module QaServer
4
+ class ScenarioRunCache
5
+ class << self
6
+ include QaServer::CacheKeys
7
+
8
+ # Run connection tests
9
+ def run_tests(force: false)
10
+ Rails.cache.fetch(cache_key_for_running_tests, expires_in: next_expiry, race_condition_ttl: 30.seconds, force: force) do
11
+ QaServer.config.monitor_logger.debug("(QaServer::ScenarioRunCache) - KICKING OFF TEST RUN (force: #{force})")
12
+ QaServer::MonitorTestsJob.perform_later
13
+ "Test run initiated at #{QaServer::TimeService.current_time}"
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def cache_key_for_running_tests
20
+ SCENARIO_RUN_TEST_DATA_CACHE_KEY
21
+ end
22
+
23
+ def next_expiry
24
+ QaServer::CacheExpiryService.cache_expiry
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+ # Maintain a cache of failure data for scenario runs
3
+ module QaServer
4
+ class ScenarioRunFailuresCache
5
+ class_attribute :scenario_history_class
6
+ self.scenario_history_class = QaServer::ScenarioRunHistory
7
+
8
+ class << self
9
+ include QaServer::CacheKeys
10
+
11
+ # Set of failures for a run
12
+ # @param run [QaServer::ScenarioRunRegistry]
13
+ # @returns [Array<Hash>] details for any failing scenarios in the run
14
+ # @example
15
+ # [ { status: :bad,
16
+ # authority_name: "geonames_ld4l_cache",
17
+ # subauthority_name: "area",
18
+ # service: "ld4l_cache",
19
+ # action: "search",
20
+ # url: "/qa/search/linked_data/geonames_ld4l_cache/area?q=France&maxRecords=4",
21
+ # err_message: "Unable to connect to authority",
22
+ # scenario_type: :connection
23
+ # run_time: 11.2 },
24
+ # { status: :unknown,
25
+ # authority_name: "oclcfast_ld4l_cache",
26
+ # subauthority_name: "Person",
27
+ # service: "ld4l_cache",
28
+ # action: "search",
29
+ # url: "/qa/search/linked_data/oclcfast_ld4l_cache/person?q=mark twain&maxRecords=4",
30
+ # err_message: "Not enough search results returned",
31
+ # scenario_type: :connection
32
+ # run_time: 0.123 } ]
33
+ def failures_for_run(run:)
34
+ Rails.cache.fetch(cache_key_for_run_failures(run.id), expires_in: next_expiry, race_condition_ttl: 30.seconds) do
35
+ QaServer.config.monitor_logger.debug("(QaServer::ScenarioRunFailuresCache) - CALCULATING FAILURES for scenario run #{run.id}")
36
+ scenario_history_class.run_failures(run_id: run.id)
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def cache_key_for_run_failures(id)
43
+ "#{SCENARIO_RUN_FAILURE_DATA_CACHE_KEY}--#{id}{"
44
+ end
45
+
46
+ def next_expiry
47
+ QaServer::CacheExpiryService.cache_expiry
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+ # Maintain a cache of summary test data for scenario runs
3
+ module QaServer
4
+ class ScenarioRunSummaryCache
5
+ class_attribute :scenario_history_class
6
+ self.scenario_history_class = QaServer::ScenarioRunHistory
7
+
8
+ class << self
9
+ include QaServer::CacheKeys
10
+
11
+ # Summary for a run
12
+ # @param run [QaServer::ScenarioRunRegistry]
13
+ # @returns [QaServer::ScenarioRunSummary] statistics on the requested run
14
+ # @example ScenarioRunSummary includes methods for accessing
15
+ # * run_id [Integer] e.g. 14
16
+ # * run_dt_stamp [ActiveSupport::TimeWithZone] e.g. Wed, 19 Feb 2020 16:01:07 UTC +00:00
17
+ # * authority_count [Integer] e.g. 22
18
+ # * failing_authority_count [Integer] e.g. 1
19
+ # * passing_scenario_count [Integer] e.g. 156
20
+ # * failing_scenario_count [Integer] e.g. 3
21
+ # * total_scenario_count [Integer] e.g. 159
22
+ def summary_for_run(run:)
23
+ Rails.cache.fetch(cache_key_for_run_summary(run.id), expires_in: next_expiry, race_condition_ttl: 30.seconds) do
24
+ QaServer.config.monitor_logger.debug("(QaServer::ScenarioRunSummaryCache) - CALCULATING SUMMARY for scenario run #{run.id}")
25
+ scenario_history_class.run_summary(scenario_run: run)
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def cache_key_for_run_summary(id)
32
+ "#{SCENARIO_RUN_SUMMARY_DATA_CACHE_KEY}--#{id}"
33
+ end
34
+
35
+ def next_expiry
36
+ QaServer::CacheExpiryService.cache_expiry
37
+ end
38
+ end
39
+ end
40
+ end
@@ -7,78 +7,63 @@ module QaServer
7
7
  include QaServer::AuthorityValidationBehavior
8
8
 
9
9
  class_attribute :presenter_class,
10
- :scenario_run_registry_class,
11
- :scenario_history_class,
12
- :performance_history_class,
13
- :graphing_service_class
10
+ :scenario_run_registry_class
14
11
  self.presenter_class = QaServer::MonitorStatusPresenter
15
12
  self.scenario_run_registry_class = QaServer::ScenarioRunRegistry
16
- self.scenario_history_class = QaServer::ScenarioRunHistory
17
- self.performance_history_class = QaServer::PerformanceHistory
18
- self.graphing_service_class = QaServer::PerformanceGraphingService
19
13
 
20
14
  # Sets up presenter with data to display in the UI
21
15
  def index
22
16
  log_header
23
- latest_test_run
17
+ update_tests
18
+ update_performance_graphs
24
19
  commit_cache if commit_cache?
25
20
  @presenter = presenter_class.new(current_summary: latest_summary,
26
21
  current_failure_data: latest_failures,
27
22
  historical_summary_data: historical_data,
28
23
  performance_data: performance_table_data)
29
- update_performance_graphs
30
- QaServer.config.monitor_logger.debug("(#{self.class}##{__method__}) DONE rendering")
24
+ QaServer.config.monitor_logger.debug("~~~~~~~~ DONE rendering monitor status")
31
25
  render 'index', status: :internal_server_error if latest_summary.failing_authority_count.positive?
32
26
  end
33
27
 
34
28
  private
35
29
 
36
- # Sets @latest_test_run [QaServer::ScenarioRunRegistry]
37
- def latest_test_run
38
- @latest_test_run ||= latest_test_run_from_cache
30
+ def update_tests
31
+ QaServer::ScenarioRunCache.run_tests(force: refresh_tests?)
39
32
  end
40
33
 
41
- # cache of latest run; runs tests if cache is expired
42
- # @see #latest_test_run_from_temp_cache
43
- def latest_test_run_from_cache
44
- Rails.cache.fetch("#{self.class}/#{__method__}", expires_in: QaServer::MonitorCacheService.cache_expiry, race_condition_ttl: 5.minutes, force: refresh_tests?) do
45
- QaServer.config.monitor_logger.debug("(#{self.class}##{__method__}) get latest run of monitoring tests - cache expired or refresh requested (force: #{refresh_tests?})")
46
- QaServer::MonitorTestsJob.perform_later
47
- scenario_run_registry_class.latest_run
48
- end
34
+ # Sets @latest_test_run [QaServer::ScenarioRunRegistry]
35
+ def latest_test_run
36
+ @latest_test_run ||= scenario_run_registry_class.latest_run
49
37
  end
50
38
 
51
- # Sets @latest_summary [QaServer::ScenarioRunSummary]
39
+ # @returns [QaServer::ScenarioRunSummary] summary statistics on the latest run
52
40
  def latest_summary
53
- scenario_history_class.run_summary(scenario_run: latest_test_run, force: refresh_tests?)
41
+ QaServer::ScenarioRunSummaryCache.summary_for_run(run: latest_test_run)
54
42
  end
55
43
 
44
+ # @returns [Array<Hash>] scenario details for any failing scenarios in the latest run
45
+ # @see QaServer::ScenarioRunHistory#run_failures for structure of output
56
46
  def latest_failures
57
- scenario_history_class.run_failures(run_id: latest_test_run.id, force: refresh_tests?)
47
+ QaServer::ScenarioRunFailuresCache.failures_for_run(run: latest_test_run)
58
48
  end
59
49
 
60
- # Sets @historical_data [Array<Hash>]
50
+ # Get a summary level of historical data
51
+ # @returns [Array<Hash>] summary of passing/failing tests for each authority
52
+ # @see QaServer::ScenarioRunHistory#historical_summary for structure of output
61
53
  def historical_data
62
- scenario_history_class.historical_summary(force: refresh_history?)
54
+ QaServer::ScenarioHistoryCache.historical_summary(force: refresh_history?)
63
55
  end
64
56
 
65
- # Sets @performance_table_data [Hash<Hash>]
66
57
  def performance_table_data
67
- display_performance_datatable? ? performance_history_class.performance_table_data(force: refresh_performance?) : {}
58
+ return {} unless QaServer.config.display_performance_graph?
59
+ QaServer::PerformanceDatatableCache.data(force: refresh_performance_table?)
68
60
  end
69
61
 
70
62
  def update_performance_graphs
71
- return unless display_performance_graph?
72
- data = performance_history_class.performance_graph_data(force: refresh_performance?)
73
- graphing_service_class.create_performance_graphs(performance_data: data)
74
- end
75
-
76
- def display_performance_datatable?
77
- @display_performance_datatable ||= QaServer.config.display_performance_datatable?
78
- end
79
-
80
- def display_performance_graph?
81
- @display_performance_graph ||= QaServer.config.display_performance_graph?
63
+ return unless QaServer.config.display_performance_graph?
64
+ QaServer::PerformanceHourlyGraphCache.generate_graphs(force: refresh_performance_graphs?)
65
+ QaServer::PerformanceDailyGraphCache.generate_graphs(force: refresh_performance_graphs?)
66
+ QaServer::PerformanceMonthlyGraphCache.generate_graphs(force: refresh_performance_graphs?)
82
67
  end
83
68
 
84
69
  def refresh?
@@ -91,18 +76,23 @@ module QaServer
91
76
  end
92
77
 
93
78
  def refresh_tests?
94
- return false unless refresh?
95
- refresh_all? || params[:refresh].casecmp?('tests')
79
+ refresh? ? (refresh_all? || params[:refresh].casecmp?('tests')) : false
96
80
  end
97
81
 
98
82
  def refresh_history?
99
- return false unless refresh?
100
- refresh_all? || params[:refresh].casecmp?('history')
83
+ refresh? ? (refresh_all? || params[:refresh].casecmp?('history')) : false
101
84
  end
102
85
 
103
86
  def refresh_performance?
104
- return false unless refresh?
105
- refresh_all? || params[:refresh].casecmp?('performance')
87
+ refresh? ? (refresh_all? || params[:refresh].casecmp?('performance')) : false
88
+ end
89
+
90
+ def refresh_performance_table?
91
+ refresh? ? (refresh_performance? || params[:refresh].casecmp?('performance_table')) : false
92
+ end
93
+
94
+ def refresh_performance_graphs?
95
+ refresh? ? (refresh_performance? || params[:refresh].casecmp?('performance_graphs')) : false
106
96
  end
107
97
 
108
98
  def commit_cache?
@@ -124,9 +114,10 @@ module QaServer
124
114
  end
125
115
 
126
116
  def log_header
127
- QaServer.config.monitor_logger.debug("------------------------------------- monitor status ---------------------------------")
128
- QaServer.config.monitor_logger.debug("(#{self.class}##{__method__}) monitor status page request (refresh_tests? # #{refresh_tests?}, " \
129
- "refresh_history? # #{refresh_history?}, refresh_performance? # #{refresh_performance?})")
117
+ QaServer.config.monitor_logger.debug("------------------------------------ monitor status -----------------------------------")
118
+ QaServer.config.monitor_logger.debug("refresh_all? #{refresh_all?}, refresh_tests? #{refresh_tests?}, refresh_history? #{refresh_history?}")
119
+ QaServer.config.monitor_logger.debug("refresh_performance? #{refresh_performance?}, refresh_performance_table? #{refresh_performance_table?}, " \
120
+ "refresh_performance_graphs? #{refresh_performance_graphs?})")
130
121
  end
131
122
  end
132
123
  end
@@ -10,7 +10,7 @@ module QaServer
10
10
  self.scenario_run_registry_class = QaServer::ScenarioRunRegistry
11
11
 
12
12
  def perform
13
- Rails.cache.fetch("QaServer::MonitorStatusController/latest_test_run_from_cache", expires_in: QaServer::MonitorCacheService.cache_expiry, race_condition_ttl: 5.minutes, force: true) do
13
+ Rails.cache.fetch("QaServer::MonitorStatusController/latest_test_run_from_cache", expires_in: QaServer::CacheExpiryService.cache_expiry, race_condition_ttl: 5.minutes, force: true) do
14
14
  job_id = SecureRandom.uuid
15
15
  monitor_tests_job_id = job_id unless monitor_tests_job_id
16
16
  run_tests if monitor_tests_job_id == job_id # avoid race conditions