Module: RSpecTracer::Storage::JsonBackend::Merger Private
- Defined in:
- lib/rspec_tracer/storage/json_backend.rb
Overview
This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.
Stateless snapshot union. parallel_tests partitions spec files across workers, so example IDs are disjoint in practice - the merge collision rules (first-wins for metadata, sum-of-ints for per-line coverage) only fire on collaborating workers that happened to observe the same input file.
Class Method Summary collapse
-
.absorb(state, snapshot) ⇒ Object
private
Union every field from one peer snapshot into the running state.
-
.call(snapshots, schema_version:) ⇒ Object
private
Internal helper for the tracer pipeline.
-
.empty_state ⇒ Object
private
Internal helper for the tracer pipeline.
-
.merge_cache_hit_reason!(target, source) ⇒ Object
private
Sum per-worker reason counts.
-
.merge_env_dependency!(target, source) ⇒ Object
private
Per-example env attribution unions set-wise: an example that declared ‘tracks: { env: [A, B] }` on one worker and `tracks: { env: [B, C] }` on another (edge case; parallel_tests workers rarely run the same example) collapses to [A, B, C].
-
.merge_examples_coverage!(target, source) ⇒ Object
private
Internal helper for the tracer pipeline.
-
.reverse_of(dependency) ⇒ Object
private
Internal helper for the tracer pipeline.
Class Method Details
.absorb(state, snapshot) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Union every field from one peer snapshot into the running state. Each field has a distinct combine rule (merge-first-wins, Set#merge, concat, or summing coverage strengths), so the branching is inherent to the shape. Decomposing per-field would scatter the merge contract. rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 |
# File 'lib/rspec_tracer/storage/json_backend.rb', line 446 def self.absorb(state, snapshot) state[:all_examples].merge!(snapshot.all_examples || {}) { |_, v, _| v } (snapshot.duplicate_examples || {}).each do |id, entries| state[:duplicate_examples][id].concat(entries) end state[:interrupted_examples].merge(snapshot.interrupted_examples || Set.new) state[:flaky_examples].merge(snapshot.flaky_examples || Set.new) state[:failed_examples].merge(snapshot.failed_examples || Set.new) state[:pending_examples].merge(snapshot.pending_examples || Set.new) state[:skipped_examples].merge(snapshot.skipped_examples || Set.new) state[:all_files].merge!(snapshot.all_files || {}) { |_, v, _| v } (snapshot.dependency || {}).each do |id, paths| state[:dependency][id].merge(paths) end merge_examples_coverage!(state[:examples_coverage], snapshot.examples_coverage || {}) state[:boot_set].merge!(snapshot.boot_set || {}) state[:wsi_snapshot].merge!(snapshot.wsi_snapshot || {}) state[:env_snapshot].merge!(snapshot.env_snapshot || {}) merge_env_dependency!(state[:env_dependency], snapshot.env_dependency || {}) merge_cache_hit_reason!(state[:cache_hit_reason], snapshot.cache_hit_reason || {}) end |
.call(snapshots, schema_version:) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Internal helper for the tracer pipeline.
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 |
# File 'lib/rspec_tracer/storage/json_backend.rb', line 389 def self.call(snapshots, schema_version:) state = empty_state snapshots.each { |s| absorb(state, s) } state[:reverse_dependency] = reverse_of(state[:dependency]) state[:run_id] = Digest::MD5.hexdigest(state[:all_examples].keys.sort.to_json) Snapshot.new( schema_version: schema_version, run_id: state[:run_id], all_examples: state[:all_examples], duplicate_examples: state[:duplicate_examples], interrupted_examples: state[:interrupted_examples], flaky_examples: state[:flaky_examples], failed_examples: state[:failed_examples], pending_examples: state[:pending_examples], skipped_examples: state[:skipped_examples], all_files: state[:all_files], dependency: state[:dependency], reverse_dependency: state[:reverse_dependency], examples_coverage: state[:examples_coverage], boot_set: state[:boot_set], wsi_snapshot: state[:wsi_snapshot], env_snapshot: state[:env_snapshot], env_dependency: state[:env_dependency], cache_hit_reason: state[:cache_hit_reason] ) end |
.empty_state ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Internal helper for the tracer pipeline.
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 |
# File 'lib/rspec_tracer/storage/json_backend.rb', line 420 def self.empty_state { all_examples: {}, duplicate_examples: Hash.new { |h, k| h[k] = [] }, interrupted_examples: Set.new, flaky_examples: Set.new, failed_examples: Set.new, pending_examples: Set.new, skipped_examples: Set.new, all_files: {}, dependency: Hash.new { |h, k| h[k] = Set.new }, examples_coverage: {}, boot_set: {}, wsi_snapshot: {}, env_snapshot: {}, env_dependency: {}, cache_hit_reason: Hash.new(0) } end |
.merge_cache_hit_reason!(target, source) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Sum per-worker reason counts. parallel_tests partitions examples across workers; each worker’s filtered_examples tally is disjoint by example_id, so sum is the right combine rule (a “Files changed” count from worker A plus the same reason’s count from worker B = total examples that ran for that reason across the suite).
486 487 488 |
# File 'lib/rspec_tracer/storage/json_backend.rb', line 486 def self.merge_cache_hit_reason!(target, source) source.each { |reason, count| target[reason] += count } end |
.merge_env_dependency!(target, source) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Per-example env attribution unions set-wise: an example that declared ‘tracks: { env: [A, B] }` on one worker and `tracks: { env: [B, C] }` on another (edge case; parallel_tests workers rarely run the same example) collapses to [A, B, C].
473 474 475 476 477 478 |
# File 'lib/rspec_tracer/storage/json_backend.rb', line 473 def self.merge_env_dependency!(target, source) source.each do |id, names| existing = target[id] || [] target[id] = (existing | Array(names)).sort end end |
.merge_examples_coverage!(target, source) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Internal helper for the tracer pipeline.
492 493 494 495 496 497 498 499 500 501 502 |
# File 'lib/rspec_tracer/storage/json_backend.rb', line 492 def self.merge_examples_coverage!(target, source) source.each do |id, per_file| entry = target[id] ||= {} per_file.each do |file_path, lines| file_entry = entry[file_path] ||= {} lines.each do |line_key, strength| file_entry[line_key] = (file_entry[line_key] || 0) + (strength || 0) end end end end |
.reverse_of(dependency) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Internal helper for the tracer pipeline.
506 507 508 509 510 511 512 |
# File 'lib/rspec_tracer/storage/json_backend.rb', line 506 def self.reverse_of(dependency) reverse = Hash.new { |h, k| h[k] = Set.new } dependency.each do |id, file_names| file_names.each { |name| reverse[name] << id } end reverse end |