bitfab 0.33.1 → 0.33.3
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 +4 -4
- data/lib/bitfab/client.rb +8 -3
- data/lib/bitfab/http_client.rb +15 -1
- data/lib/bitfab/replay.rb +35 -18
- data/lib/bitfab/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 44ebaac53c01dd84f179de5559eb3f00836c6c1a51f15520b8f10085bcfd6021
|
|
4
|
+
data.tar.gz: b7255113aef3706aefd3a1017520f24e6127503418965a0db23e70573fdd3d0e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: de1b1c86dc8660477b87632d766e6f8fdf858d682248c9bd53d024fb3b423acc18d02d877ff567344e5a80aa686d0ad3e72bb02e8cc7dd099612e28ccdc02ad2
|
|
7
|
+
data.tar.gz: bb0ea7013f448acffa4644a359c0c38198ce9c74caf2b77c3d4d4c80a3f5b6f6f0bd73591ffd653b97c99af6518bc0c12460d69ac65314faf5d047541d731d1c
|
data/lib/bitfab/client.rb
CHANGED
|
@@ -76,9 +76,14 @@ module Bitfab
|
|
|
76
76
|
# @param trace_ids [Array<String>, nil] optional list of trace IDs to replay (max 100)
|
|
77
77
|
# @param max_concurrency [Integer, nil] max threads for parallel replay (default: 10)
|
|
78
78
|
# @param code_change_description [String, nil] optional rationale for the
|
|
79
|
-
# code change being tested in this replay (stored on the experiment)
|
|
79
|
+
# code change being tested in this replay (stored on the experiment).
|
|
80
|
+
# When supplied without code_change_files, this text is preserved while
|
|
81
|
+
# the SDK automatically captures the files.
|
|
82
|
+
# Pass nil when the replay should have no description; use
|
|
83
|
+
# code_change_files: nil to suppress automatic file capture.
|
|
80
84
|
# @param code_change_files [Array<Hash>, nil] optional list of edited files,
|
|
81
|
-
# each as { path:, before:, after: } (use "" for new/deleted files)
|
|
85
|
+
# each as { path:, before:, after: } (use "" for new/deleted files).
|
|
86
|
+
# Omit to capture automatically, or pass nil to suppress file capture.
|
|
82
87
|
# @param experiment_group_id [String, nil] optional UUID grouping multiple
|
|
83
88
|
# replay runs into a single experiment batch
|
|
84
89
|
# @param dataset_id [String, nil] optional UUID of the dataset this replay
|
|
@@ -118,7 +123,7 @@ module Bitfab
|
|
|
118
123
|
# A raising callback never crashes the run.
|
|
119
124
|
# @return [Hash] with :items, :test_run_id, :test_run_url
|
|
120
125
|
def replay(receiver, method_name, trace_function_key:, limit: nil, trace_ids: nil, max_concurrency: 10,
|
|
121
|
-
name: nil, code_change_description:
|
|
126
|
+
name: nil, code_change_description: Replay::CODE_CHANGE_UNSET, code_change_files: Replay::CODE_CHANGE_UNSET, experiment_group_id: nil, dataset_id: nil, grader_ids: nil, mock: "marked",
|
|
122
127
|
adapt_inputs: nil, mock_override: nil, db_branch: nil, on_progress: nil)
|
|
123
128
|
Replay.run(
|
|
124
129
|
self, receiver, method_name,
|
data/lib/bitfab/http_client.rb
CHANGED
|
@@ -11,6 +11,9 @@ require_relative "warn_once"
|
|
|
11
11
|
|
|
12
12
|
module Bitfab
|
|
13
13
|
class HttpClient
|
|
14
|
+
REPLAY_DB_BRANCH_REQUEST_TIMEOUT_SECONDS = 300
|
|
15
|
+
private_constant :REPLAY_DB_BRANCH_REQUEST_TIMEOUT_SECONDS
|
|
16
|
+
|
|
14
17
|
attr_reader :service_url
|
|
15
18
|
|
|
16
19
|
def initialize(api_key:, service_url: nil, timeout: 120)
|
|
@@ -131,6 +134,7 @@ module Bitfab
|
|
|
131
134
|
payload["codeChangeFiles"] = normalize_code_change_files(code_change_files) unless code_change_files.nil?
|
|
132
135
|
payload["experimentGroupId"] = experiment_group_id unless experiment_group_id.nil?
|
|
133
136
|
payload["includeDbBranchLease"] = true if include_db_branch_lease
|
|
137
|
+
payload["lazyDbBranchLease"] = true if include_db_branch_lease
|
|
134
138
|
payload["datasetId"] = dataset_id unless dataset_id.nil?
|
|
135
139
|
payload["graderIds"] = grader_ids unless grader_ids.nil?
|
|
136
140
|
payload["dbBranchSettings"] = db_branch_settings unless db_branch_settings.nil?
|
|
@@ -143,7 +147,7 @@ module Bitfab
|
|
|
143
147
|
# sits above the server's own ceiling so the server's error is the one
|
|
144
148
|
# callers see. Net::HTTP would otherwise default to 60s here, which the
|
|
145
149
|
# branch creation alone can outlast.
|
|
146
|
-
timeout = include_db_branch_lease ?
|
|
150
|
+
timeout = include_db_branch_lease ? REPLAY_DB_BRANCH_REQUEST_TIMEOUT_SECONDS : 30
|
|
147
151
|
request("/api/sdk/replay/start", payload, timeout:)
|
|
148
152
|
end
|
|
149
153
|
|
|
@@ -194,6 +198,16 @@ module Bitfab
|
|
|
194
198
|
request("/api/sdk/replay/releaseDbBranchLease", {"neonBranchId" => neon_branch_id}, timeout: 30)
|
|
195
199
|
end
|
|
196
200
|
|
|
201
|
+
def resolve_db_branch_lease(test_run_id, trace_id, db_branch_settings = nil)
|
|
202
|
+
payload = {"testRunId" => test_run_id, "traceId" => trace_id}
|
|
203
|
+
payload["dbBranchSettings"] = db_branch_settings unless db_branch_settings.nil?
|
|
204
|
+
request(
|
|
205
|
+
"/api/sdk/replay/resolveDbBranchLease",
|
|
206
|
+
payload,
|
|
207
|
+
timeout: REPLAY_DB_BRANCH_REQUEST_TIMEOUT_SECONDS
|
|
208
|
+
)
|
|
209
|
+
end
|
|
210
|
+
|
|
197
211
|
# Send an external trace (fire-and-forget in background thread).
|
|
198
212
|
def send_external_trace(payload)
|
|
199
213
|
merged = payload.merge("sdkVersion" => VERSION)
|
data/lib/bitfab/replay.rb
CHANGED
|
@@ -81,6 +81,8 @@ module Bitfab
|
|
|
81
81
|
|
|
82
82
|
# Replay historical traces through a traced method and create a test run.
|
|
83
83
|
module Replay
|
|
84
|
+
CODE_CHANGE_UNSET = Object.new.freeze
|
|
85
|
+
|
|
84
86
|
module_function
|
|
85
87
|
|
|
86
88
|
# Replay historical traces through a method and create a test run.
|
|
@@ -99,9 +101,14 @@ module Bitfab
|
|
|
99
101
|
# @param name [String, nil] optional display name for the resulting experiment/test run
|
|
100
102
|
# @param max_concurrency [Integer, nil] max threads for parallel replay (default: 10)
|
|
101
103
|
# @param code_change_description [String, nil] optional rationale for the
|
|
102
|
-
# code change being tested in this replay (stored on the experiment)
|
|
104
|
+
# code change being tested in this replay (stored on the experiment).
|
|
105
|
+
# When supplied without code_change_files, this text is preserved while
|
|
106
|
+
# the SDK automatically captures the files.
|
|
107
|
+
# Pass nil when the replay should have no description; use
|
|
108
|
+
# code_change_files: nil to suppress automatic file capture.
|
|
103
109
|
# @param code_change_files [Array<Hash>, nil] optional list of edited files,
|
|
104
|
-
# each as { path:, before:, after: } (empty string for new/deleted files)
|
|
110
|
+
# each as { path:, before:, after: } (empty string for new/deleted files).
|
|
111
|
+
# Omit to capture automatically, or pass nil to suppress file capture.
|
|
105
112
|
# @param experiment_group_id [String, nil] optional UUID grouping multiple
|
|
106
113
|
# replay runs into a single experiment batch
|
|
107
114
|
# @param dataset_id [String, nil] optional UUID of the dataset this replay
|
|
@@ -140,7 +147,7 @@ module Bitfab
|
|
|
140
147
|
# crashes the run.
|
|
141
148
|
# @return [Hash] with :items, :test_run_id, :test_run_url
|
|
142
149
|
def run(client, receiver, method_name, trace_function_key:, limit: nil, trace_ids: nil, name: nil,
|
|
143
|
-
max_concurrency: 10, code_change_description:
|
|
150
|
+
max_concurrency: 10, code_change_description: CODE_CHANGE_UNSET, code_change_files: CODE_CHANGE_UNSET, experiment_group_id: nil,
|
|
144
151
|
dataset_id: nil, grader_ids: nil, mock: "marked",
|
|
145
152
|
adapt_inputs: nil, mock_override: nil, db_branch: nil, on_progress: nil)
|
|
146
153
|
unless MOCK_STRATEGIES.include?(mock.to_s)
|
|
@@ -187,19 +194,20 @@ module Bitfab
|
|
|
187
194
|
|
|
188
195
|
include_db_branch_lease = !db_branch.nil?
|
|
189
196
|
|
|
190
|
-
#
|
|
191
|
-
#
|
|
192
|
-
#
|
|
193
|
-
|
|
194
|
-
# assistant's make-change rails.
|
|
195
|
-
if code_change_description.nil? && code_change_files.nil?
|
|
197
|
+
# code_change_files controls capture: omitted auto-captures, an array
|
|
198
|
+
# wins, and explicit nil opts out. Preserve a caller-supplied description
|
|
199
|
+
# while filling only the omitted files.
|
|
200
|
+
if code_change_files.equal?(CODE_CHANGE_UNSET)
|
|
196
201
|
captured = resolve_auto_code_change(name)
|
|
197
202
|
unless captured.nil?
|
|
198
|
-
code_change_description = captured[0]
|
|
199
203
|
code_change_files = captured[1]
|
|
204
|
+
code_change_description = captured[0] if code_change_description.equal?(CODE_CHANGE_UNSET)
|
|
200
205
|
end
|
|
201
206
|
end
|
|
207
|
+
code_change_description = nil if code_change_description.equal?(CODE_CHANGE_UNSET)
|
|
208
|
+
code_change_files = nil if code_change_files.equal?(CODE_CHANGE_UNSET)
|
|
202
209
|
|
|
210
|
+
resolved_db_branch_settings = db_branch_settings(db_branch)
|
|
203
211
|
replay_data = http_client.start_replay(
|
|
204
212
|
trace_function_key,
|
|
205
213
|
effective_limit,
|
|
@@ -211,7 +219,7 @@ module Bitfab
|
|
|
211
219
|
include_db_branch_lease:,
|
|
212
220
|
dataset_id:,
|
|
213
221
|
grader_ids:,
|
|
214
|
-
db_branch_settings:
|
|
222
|
+
db_branch_settings: resolved_db_branch_settings
|
|
215
223
|
)
|
|
216
224
|
test_run_id = replay_data["testRunId"]
|
|
217
225
|
test_run_url = replay_data["testRunUrl"]
|
|
@@ -219,7 +227,8 @@ module Bitfab
|
|
|
219
227
|
|
|
220
228
|
result_items = if server_items.any?
|
|
221
229
|
process_items(http_client, server_items, receiver, method_name, test_run_id, max_concurrency, mock.to_s,
|
|
222
|
-
adapt_inputs, include_db_branch_lease, on_progress:,
|
|
230
|
+
adapt_inputs, include_db_branch_lease, resolved_db_branch_settings, on_progress:,
|
|
231
|
+
mock_overrides: resolved_overrides)
|
|
223
232
|
else
|
|
224
233
|
[]
|
|
225
234
|
end
|
|
@@ -528,7 +537,8 @@ module Bitfab
|
|
|
528
537
|
|
|
529
538
|
# Process all replay items, optionally in parallel using threads.
|
|
530
539
|
def process_items(http_client, server_items, receiver, method_name, test_run_id, max_concurrency, mock_strategy,
|
|
531
|
-
adapt_inputs = nil, include_db_branch_lease = false,
|
|
540
|
+
adapt_inputs = nil, include_db_branch_lease = false, db_branch_settings = nil, on_progress: nil,
|
|
541
|
+
mock_overrides: [])
|
|
532
542
|
concurrency = max_concurrency || server_items.length
|
|
533
543
|
|
|
534
544
|
# Reports running totals once per item as it settles. In the parallel
|
|
@@ -584,7 +594,7 @@ module Bitfab
|
|
|
584
594
|
if concurrency <= 1
|
|
585
595
|
server_items.map do |item|
|
|
586
596
|
result = process_single_item(http_client, item, receiver, method_name, test_run_id, mock_strategy,
|
|
587
|
-
adapt_inputs, include_db_branch_lease, mock_overrides:)
|
|
597
|
+
adapt_inputs, include_db_branch_lease, db_branch_settings, mock_overrides:)
|
|
588
598
|
report.call(result, original_trace_id_of(item), original_span_id_of(item), test_run_id)
|
|
589
599
|
result
|
|
590
600
|
end
|
|
@@ -601,7 +611,7 @@ module Bitfab
|
|
|
601
611
|
break unless item
|
|
602
612
|
|
|
603
613
|
result = process_single_item(http_client, item, receiver, method_name, test_run_id, mock_strategy,
|
|
604
|
-
adapt_inputs, include_db_branch_lease, mock_overrides:)
|
|
614
|
+
adapt_inputs, include_db_branch_lease, db_branch_settings, mock_overrides:)
|
|
605
615
|
results_mutex.synchronize { results[idx] = result }
|
|
606
616
|
report.call(result, original_trace_id_of(item), original_span_id_of(item), test_run_id)
|
|
607
617
|
end
|
|
@@ -620,7 +630,7 @@ module Bitfab
|
|
|
620
630
|
# than propagated, so one bad trace never aborts the whole replay run
|
|
621
631
|
# (mirrors the TypeScript and Python SDKs' per-item rescue).
|
|
622
632
|
def process_single_item(http_client, server_item, receiver, method_name, test_run_id, mock_strategy,
|
|
623
|
-
adapt_inputs = nil, include_db_branch_lease = false, mock_overrides: [])
|
|
633
|
+
adapt_inputs = nil, include_db_branch_lease = false, db_branch_settings = nil, mock_overrides: [])
|
|
624
634
|
metrics = extract_server_item_metrics(server_item)
|
|
625
635
|
# The ORIGINAL (historical) trace/span this item replays. Canonical
|
|
626
636
|
# keys are originalTraceId/originalSpanId; older servers send them under
|
|
@@ -638,6 +648,13 @@ module Bitfab
|
|
|
638
648
|
# for a branch, so running their method against live data would produce a
|
|
639
649
|
# result that looks valid and is not. Fail the item instead, loudly.
|
|
640
650
|
lease_error = include_db_branch_lease ? server_item["dbBranchLeaseError"] : nil
|
|
651
|
+
db_snapshot_ref = server_item["dbSnapshotRef"]
|
|
652
|
+
if include_db_branch_lease && lease.nil? && lease_error.nil?
|
|
653
|
+
resolved = http_client.resolve_db_branch_lease(test_run_id, original_trace_id, db_branch_settings)
|
|
654
|
+
lease = resolved["lease"]
|
|
655
|
+
lease_error = resolved["leaseError"]
|
|
656
|
+
db_snapshot_ref = resolved["dbSnapshotRef"] || db_snapshot_ref
|
|
657
|
+
end
|
|
641
658
|
if lease_error
|
|
642
659
|
raise "Replay requested a database branch for trace #{original_trace_id} but it " \
|
|
643
660
|
"could not be resolved (#{lease_error["code"]}): #{lease_error["message"]}. " \
|
|
@@ -709,7 +726,7 @@ module Bitfab
|
|
|
709
726
|
adapt_ctx:,
|
|
710
727
|
db_branch_lease: lease,
|
|
711
728
|
source_bitfab_trace_id: original_trace_id,
|
|
712
|
-
db_snapshot_ref:
|
|
729
|
+
db_snapshot_ref:
|
|
713
730
|
)
|
|
714
731
|
rescue => e
|
|
715
732
|
warn "Bitfab: replay item for span #{original_span_id} failed before execution: #{e.message}"
|
|
@@ -727,7 +744,7 @@ module Bitfab
|
|
|
727
744
|
# Deprecated aliases for original_trace_id/original_span_id.
|
|
728
745
|
source_trace_id: original_trace_id,
|
|
729
746
|
source_span_id: original_span_id,
|
|
730
|
-
db_snapshot_ref:
|
|
747
|
+
db_snapshot_ref:
|
|
731
748
|
}
|
|
732
749
|
ensure
|
|
733
750
|
release_db_branch_lease(http_client, lease) if lease
|
data/lib/bitfab/version.rb
CHANGED