Module: Bitfab::ReplayContext
- Defined in:
- lib/bitfab/replay.rb
Overview
Replay context shared by fibers on the current thread. Ruby's Thread#[] storage is fiber-local, so use true thread variables here: lazy Enumerator bodies run in another fiber but must retain replay mocking.
Class Method Summary collapse
- .current ⇒ Object
- .current_span ⇒ Object
-
.with_context(test_run_id:, input_source_span_id: nil, input_source_trace_id: nil, trace_id: nil, mock_tree: nil, mock_strategy: nil, mock_overrides: nil, fetch_span_output: nil, db_branch_lease: nil, db_branch_timings: nil, source_bitfab_trace_id: nil) ⇒ Object
Execute a block with replay context set for every fiber on the current thread.
- .with_span(trace_id:, span_id:) ⇒ Object
Class Method Details
.current ⇒ Object
54 55 56 |
# File 'lib/bitfab/replay.rb', line 54 def current Thread.current.thread_variable_get(REPLAY_CONTEXT_KEY) end |
.current_span ⇒ Object
58 59 60 |
# File 'lib/bitfab/replay.rb', line 58 def current_span current&.dig(:span_stack)&.last end |
.with_context(test_run_id:, input_source_span_id: nil, input_source_trace_id: nil, trace_id: nil, mock_tree: nil, mock_strategy: nil, mock_overrides: nil, fetch_span_output: nil, db_branch_lease: nil, db_branch_timings: nil, source_bitfab_trace_id: nil) ⇒ Object
Execute a block with replay context set for every fiber on the current thread. Child threads and processes intentionally do not inherit it.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/bitfab/replay.rb', line 75 def with_context(test_run_id:, input_source_span_id: nil, input_source_trace_id: nil, trace_id: nil, mock_tree: nil, mock_strategy: nil, mock_overrides: nil, fetch_span_output: nil, db_branch_lease: nil, db_branch_timings: nil, source_bitfab_trace_id: nil) previous = Thread.current.thread_variable_get(REPLAY_CONTEXT_KEY) ctx = { test_run_id:, input_source_span_id:, input_source_trace_id:, trace_id:, span_stack: [] } if mock_tree ctx[:mock_tree] = mock_tree ctx[:mock_strategy] = mock_strategy || "marked" ctx[:call_counters] = {} # Selective mock overrides ride alongside the tree: they gate on the # same non-root call-counter machinery, so they only fire when a tree # is present. process_single_item fetches the tree whenever overrides # exist, even under mock: "none". ctx[:mock_overrides] = mock_overrides if mock_overrides && !mock_overrides.empty? # Lazy per-span output fetcher for a payload-free non-"all" tree path. # Absent on the eager "all" path, whose outputs are inline even when # overrides are present. ctx[:fetch_span_output] = fetch_span_output if fetch_span_output end # The per-trace DB branch (resolved server-side) and the Bitfab trace ID # it belongs to ride on the context so ReplayBranch can read them inside # the replayed method. # # ReplayBranch also sets ctx[:db_snapshot_accessed] = true the first # time customer code actually obtains the branch URL for this item # (via +database_url+). Reported on the trace # completion inside the +db_snapshot_usage+ record (its +accessed+ # field) so the server can distinguish "branch was provisioned and # exposed" from "branch URL was actually consumed". Only an explicit # +database_url+ read may set it. A path that hands the URL over by other # means (e.g. a process-isolated runner writing an env overlay) must # leave it alone: setting it there would make every such replay report # accessed for free, and the flag would stop separating "branch was # used" from "branch was offered". ctx[:db_branch_lease] = db_branch_lease if db_branch_lease # Kept off ReplayBranch: customer code reads that mid-replay to reach the # branch, and provisioning latency is a property of the run, not of the # connection. It rides the context only to be echoed on the completion. ctx[:db_branch_timings] = db_branch_timings if db_branch_timings ctx[:source_bitfab_trace_id] = source_bitfab_trace_id if source_bitfab_trace_id Thread.current.thread_variable_set(REPLAY_CONTEXT_KEY, ctx) yield ensure Thread.current.thread_variable_set(REPLAY_CONTEXT_KEY, previous) end |
.with_span(trace_id:, span_id:) ⇒ Object
62 63 64 65 66 67 68 69 70 71 |
# File 'lib/bitfab/replay.rb', line 62 def with_span(trace_id:, span_id:) ctx = current return yield unless ctx entry = {trace_id:, span_id:} ctx[:span_stack].push(entry) yield ensure ctx[:span_stack].pop if ctx end |