bitfab 0.15.0 → 0.16.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b0e39c364993d34e99e1d7e3c3a878e0fc6fbfe685fcb0335128bfbf7252161b
4
- data.tar.gz: 54bcd62faffceac5c0f67f26f5dedbed0057061019d24d1d789f9988fbf0a44a
3
+ metadata.gz: 3320e43b6f1be704f5ab955161b347d954691c6cdc75f5e57ab01452e8f8dd7f
4
+ data.tar.gz: 2b8872ef106d63560d6718ab4d2076f6271417fbc56e44581c2e4f5058ff4a00
5
5
  SHA512:
6
- metadata.gz: 04cef22ee4135b8c43e1e35f5ead74f5650d9f49e16b818de05980d01a054b145bf4adbad1c9fc3ec01b0e17130e108df666f75bc8bc9bf4666eb23eb9ba7acc
7
- data.tar.gz: bb4724aff3d7fc6a9f04e1a923fd5aaabb2e808ef2310ef2c1d51e6a246c296653c1ea85509a92e1a1b927c131074e0907c07623ade5affaa6bab8fd20b2464c
6
+ metadata.gz: f9599b68cfbac6812070bfd05516b1372e607e5cc2214a5e7319ca39b5e22c80390db4b3446e6c136bea2c2a0780e8ffeab5fbb99226e2bf7636ace35a9a72f5
7
+ data.tar.gz: 98c9855c1d5f3cb4403926820b223733c555696211ab27d0980c06f9f38e01aa02b0e4c2065525c33eed6bd8e60f0136b3a4951a67416051181287b5f7acbc7a
data/lib/bitfab/client.rb CHANGED
@@ -53,13 +53,18 @@ module Bitfab
53
53
  # @param mock [String] mock strategy for child spans: "none" (default),
54
54
  # "all", or "marked". "all" mocks every child span; "marked" only mocks
55
55
  # spans declared with mock_on_replay: true.
56
+ # @param adapt_inputs [#call, nil] optional hook to reshape recorded inputs
57
+ # onto the method's current signature when its shape changed after the
58
+ # traces were captured. Receives (args, kwargs, ctx) where ctx is
59
+ # { trace_id:, source_span_id: }, and returns [new_args, new_kwargs].
56
60
  # @return [Hash] with :items, :test_run_id, :test_run_url
57
61
  def replay(receiver, method_name, trace_function_key:, limit: nil, trace_ids: nil, max_concurrency: 10,
58
- code_change_description: nil, code_change_files: nil, experiment_group_id: nil, mock: "none")
62
+ code_change_description: nil, code_change_files: nil, experiment_group_id: nil, mock: "none",
63
+ adapt_inputs: nil)
59
64
  Replay.run(
60
65
  self, receiver, method_name,
61
66
  trace_function_key:, limit:, trace_ids:, max_concurrency:,
62
- code_change_description:, code_change_files:, experiment_group_id:, mock:
67
+ code_change_description:, code_change_files:, experiment_group_id:, mock:, adapt_inputs:
63
68
  )
64
69
  end
65
70
 
data/lib/bitfab/replay.rb CHANGED
@@ -75,9 +75,16 @@ module Bitfab
75
75
  # @param mock [String] mock strategy for child spans: "none" (default),
76
76
  # "all", or "marked". "all" mocks every child span; "marked" only mocks
77
77
  # spans declared with mock_on_replay: true.
78
+ # @param adapt_inputs [#call, nil] optional hook to reshape recorded inputs
79
+ # onto the method's current signature when its shape changed after the
80
+ # traces were captured. Receives (args, kwargs, ctx) where ctx is
81
+ # { trace_id:, source_span_id: }, and returns [new_args, new_kwargs]. Runs
82
+ # per item inside the same rescue as the method, so a raising adapter sets
83
+ # that item's :error rather than crashing the run.
78
84
  # @return [Hash] with :items, :test_run_id, :test_run_url
79
85
  def run(client, receiver, method_name, trace_function_key:, limit: nil, trace_ids: nil, max_concurrency: 10,
80
- code_change_description: nil, code_change_files: nil, experiment_group_id: nil, mock: "none")
86
+ code_change_description: nil, code_change_files: nil, experiment_group_id: nil, mock: "none",
87
+ adapt_inputs: nil)
81
88
  unless MOCK_STRATEGIES.include?(mock.to_s)
82
89
  raise ArgumentError, "Invalid mock strategy '#{mock}'. Must be one of: #{MOCK_STRATEGIES.join(", ")}"
83
90
  end
@@ -111,7 +118,8 @@ module Bitfab
111
118
  server_items = replay_data["items"] || []
112
119
 
113
120
  result_items = if server_items.any?
114
- process_items(http_client, server_items, receiver, method_name, test_run_id, max_concurrency, mock.to_s)
121
+ process_items(http_client, server_items, receiver, method_name, test_run_id, max_concurrency, mock.to_s,
122
+ adapt_inputs)
115
123
  else
116
124
  []
117
125
  end
@@ -183,12 +191,13 @@ module Bitfab
183
191
  end
184
192
 
185
193
  # Process all replay items, optionally in parallel using threads.
186
- def process_items(http_client, server_items, receiver, method_name, test_run_id, max_concurrency, mock_strategy)
194
+ def process_items(http_client, server_items, receiver, method_name, test_run_id, max_concurrency, mock_strategy,
195
+ adapt_inputs = nil)
187
196
  concurrency = max_concurrency || server_items.length
188
197
 
189
198
  if concurrency <= 1
190
199
  server_items.map do |item|
191
- process_single_item(http_client, item, receiver, method_name, test_run_id, mock_strategy)
200
+ process_single_item(http_client, item, receiver, method_name, test_run_id, mock_strategy, adapt_inputs)
192
201
  end
193
202
  else
194
203
  results_mutex = Mutex.new
@@ -202,7 +211,8 @@ module Bitfab
202
211
  item, idx = work_mutex.synchronize { work_queue.shift }
203
212
  break unless item
204
213
 
205
- result = process_single_item(http_client, item, receiver, method_name, test_run_id, mock_strategy)
214
+ result = process_single_item(http_client, item, receiver, method_name, test_run_id, mock_strategy,
215
+ adapt_inputs)
206
216
  results_mutex.synchronize { results[idx] = result }
207
217
  end
208
218
  end
@@ -219,7 +229,8 @@ module Bitfab
219
229
  # deserializing inputs is captured on the returned item's :error rather
220
230
  # than propagated, so one bad trace never aborts the whole replay run
221
231
  # (mirrors the TypeScript and Python SDKs' per-item rescue).
222
- def process_single_item(http_client, server_item, receiver, method_name, test_run_id, mock_strategy)
232
+ def process_single_item(http_client, server_item, receiver, method_name, test_run_id, mock_strategy,
233
+ adapt_inputs = nil)
223
234
  metrics = extract_server_item_metrics(server_item)
224
235
 
225
236
  span = http_client.get_external_span(server_item["externalSpanId"])
@@ -231,6 +242,8 @@ module Bitfab
231
242
  mock_tree = build_mock_tree(tree["root"] || {})
232
243
  end
233
244
 
245
+ adapt_ctx = {trace_id: server_item["traceId"], source_span_id: server_item["externalSpanId"]}
246
+
234
247
  execute_item(
235
248
  item_data,
236
249
  receiver,
@@ -240,7 +253,9 @@ module Bitfab
240
253
  metrics,
241
254
  input_source_trace_id: span["externalTraceId"],
242
255
  mock_strategy:,
243
- mock_tree:
256
+ mock_tree:,
257
+ adapt_inputs:,
258
+ adapt_ctx:
244
259
  )
245
260
  rescue => e
246
261
  warn "Bitfab: replay item for span #{server_item["externalSpanId"]} failed before execution: #{e.message}"
@@ -331,7 +346,7 @@ module Bitfab
331
346
 
332
347
  # Execute a single replay item: deserialize inputs, call method with replay context.
333
348
  def execute_item(item, receiver, method_name, test_run_id, input_source_span_id = nil, metrics = {},
334
- input_source_trace_id: nil, mock_strategy: "none", mock_tree: nil)
349
+ input_source_trace_id: nil, mock_strategy: "none", mock_tree: nil, adapt_inputs: nil, adapt_ctx: nil)
335
350
  args, kwargs = Serialize.deserialize_inputs(item)
336
351
 
337
352
  fn_result = nil
@@ -352,6 +367,13 @@ module Bitfab
352
367
  mock_strategy:,
353
368
  pending_persistence:
354
369
  ) do
370
+ # Reshape recorded inputs onto the current signature when an adapter is
371
+ # supplied. Inside the rescue so a raising adapter surfaces on this
372
+ # item's :error instead of crashing the run; args is reported on :input.
373
+ if adapt_inputs
374
+ ctx = adapt_ctx || {trace_id: nil, source_span_id: input_source_span_id}
375
+ args, kwargs = adapt_inputs.call(args, kwargs, ctx)
376
+ end
355
377
  fn_result = if kwargs.empty?
356
378
  receiver.send(method_name, *args)
357
379
  else
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bitfab
4
- VERSION = "0.15.0"
4
+ VERSION = "0.16.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitfab
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.0
4
+ version: 0.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harvest Team