Class: Eco::API::UseCases::GraphQL::Compat::Parity::Harness

Inherits:
Object
  • Object
show all
Defined in:
lib/eco/api/usecases/graphql/compat/parity/harness.rb

Overview

A/B parity harness for the ooze -> native GraphQL strangler-fig migration.

Runs the SAME logical register-processing case through the two code paths — A: legacy (v2 / OozeRedirect shim), B: native GraphQL — and asserts that the observable outcome (KPI counters + per-page update payloads) is equivalent.

The comparison logic (RunResult / Comparison) is PURE and offline-runnable. The harness itself is a thin orchestrator: you hand it two callables, each of which runs its side and returns a RunResult. In a live run each callable would execute the case in -simulate mode against the same test org, using a Recorder to capture what each side WOULD write (no data is mutated). Wiring the two live runs needs credentials + a test org; the structural machinery here is verified offline.

== Usage (live)

harness = Parity::Harness.new( legacy: -> { Parity::Harness.record('legacy') { |rec| run_legacy_case(rec) } }, native: -> { Parity::Harness.record('native') { |rec| run_native_case(rec) } } ) comparison = harness.run raise comparison.report unless comparison.equivalent?

== Usage (offline / spec)

a = Parity::RunResult.new(label: 'legacy', kpis: ..., updates: ...) b = Parity::RunResult.new(label: 'native', kpis: ..., updates: ...) Parity::Harness.new(legacy: -> { a }, native: -> { b }).run.equivalent?

Defined Under Namespace

Classes: Recorder

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(legacy:, native:) ⇒ Harness

Returns a new instance of Harness.

Parameters:

  • legacy (#call)

    returns the legacy-path RunResult.

  • native (#call)

    returns the native-path RunResult.



34
35
36
37
# File 'lib/eco/api/usecases/graphql/compat/parity/harness.rb', line 34

def initialize(legacy:, native:)
  @legacy = legacy
  @native = native
end

Class Method Details

.record(label) {|recorder| ... } ⇒ RunResult

Capture the observable outcome of a case run into a RunResult.

Yields a Recorder. The caller runs the case, feeding each page's would-be update payload to recorder.record_update(page_id, payload) (typically wired by stubbing the case's update_page to call graphql.pages.get_body(page) instead of persisting). After the run, pass the case's KPI hash to recorder.kpis = case.kpis_hash (or set counters individually).

Parameters:

  • label (String)

    'legacy' or 'native'.

Yield Parameters:

Returns:



59
60
61
62
63
# File 'lib/eco/api/usecases/graphql/compat/parity/harness.rb', line 59

def self.record(label)
  recorder = Recorder.new(label)
  yield(recorder) if block_given?
  recorder.to_run_result
end

Instance Method Details

#runObject

Execute both sides and compare. Returns a Parity::Comparison.



40
41
42
43
44
45
46
# File 'lib/eco/api/usecases/graphql/compat/parity/harness.rb', line 40

def run
  a = @legacy.call
  b = @native.call
  assert_run_result!(a, 'legacy')
  assert_run_result!(b, 'native')
  a.compare_to(b)
end