bitfab 0.43.1 → 0.51.1
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 +16 -7
- data/lib/bitfab/http_client.rb +13 -4
- data/lib/bitfab/replay.rb +26 -8
- data/lib/bitfab/replay_registry.rb +71 -21
- 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: 3dd6fa16ae3ff5f26d94f6b86f9fa702129cfb502e3f94b293e383d107d1c0de
|
|
4
|
+
data.tar.gz: 220cdb686e1a5522fdcd9579e897f60b0896360583b49615006f0489723c6d21
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cf75d4072ac82e17312f40f86c1a0e54c3a60a019818695507a5d53cfc1bfb15db6e705ad6a971c6e77abd67b4b752e180457d483b5f42becc52167323784dd9
|
|
7
|
+
data.tar.gz: 8857e35745377b128479948ec4622ef2223f3876015f03e161ac80e43f61ec1c1556cb4d4839dd174c35afba9b3e1fbfcbd0c4da69766b80cd593cd8caf96c07
|
data/lib/bitfab/client.rb
CHANGED
|
@@ -93,11 +93,14 @@ module Bitfab
|
|
|
93
93
|
# @param method_name [Symbol] the method to replay
|
|
94
94
|
# @param trace_function_key [String] the trace function key for this method
|
|
95
95
|
# @param limit [Integer, nil] maximum number of traces to replay (default: 5;
|
|
96
|
-
# maximum: 5,000). Ignored when trace_ids or
|
|
96
|
+
# maximum: 5,000). Ignored when trace_ids or a dataset is passed because
|
|
97
97
|
# either source already determines how many traces replay. Supplying
|
|
98
|
-
# trace_ids also emits a warning.
|
|
99
|
-
#
|
|
100
|
-
#
|
|
98
|
+
# trace_ids also emits a warning. To replay part of a dataset selection,
|
|
99
|
+
# name the members to run in trace_ids rather than bounding it here.
|
|
100
|
+
# @param trace_ids [Array<String>, nil] optional list of trace IDs to replay (max 100).
|
|
101
|
+
# Passed alongside dataset_id or dataset_ids it pins which members of that
|
|
102
|
+
# selection replay, and the server rejects any ID none of those datasets
|
|
103
|
+
# contains
|
|
101
104
|
# @param max_concurrency [Integer, nil] max threads for parallel replay (default: 10)
|
|
102
105
|
# @param code_change_description [String, nil] optional rationale for the
|
|
103
106
|
# code change being tested in this replay (stored on the experiment).
|
|
@@ -110,9 +113,14 @@ module Bitfab
|
|
|
110
113
|
# Omit to capture automatically, or pass nil to suppress file capture.
|
|
111
114
|
# @param experiment_group_id [String, nil] optional UUID grouping multiple
|
|
112
115
|
# replay runs into a single experiment batch
|
|
116
|
+
# @param dataset_ids [Array<String>, nil] optional UUIDs of the datasets this
|
|
117
|
+
# replay runs against, for benchmarking one method against several corpora
|
|
118
|
+
# in a single run; mutually exclusive with dataset_id. Passing trace_ids
|
|
119
|
+
# alongside it narrows the run to those members
|
|
113
120
|
# @param dataset_id [String, nil] optional UUID of the dataset this replay
|
|
114
|
-
# runs against, mutually exclusive with
|
|
115
|
-
# resulting experiment for durable attribution
|
|
121
|
+
# runs against, mutually exclusive with dataset_ids and stored on the
|
|
122
|
+
# resulting experiment for durable attribution. Alone it replays the
|
|
123
|
+
# dataset's full membership, and with trace_ids only those members
|
|
116
124
|
# @param grader_ids [Array<String>, nil] optional UUIDs of graders attached
|
|
117
125
|
# directly to this experiment, graded as the union with the dataset's
|
|
118
126
|
# runnable graders at completion; each must be an active/live grader in the
|
|
@@ -158,7 +166,7 @@ module Bitfab
|
|
|
158
166
|
# queued work from in-flight work. A raising callback never crashes the run.
|
|
159
167
|
# @return [Hash] with :items, :test_run_id, :test_run_url
|
|
160
168
|
def replay(receiver, method_name, trace_function_key:, limit: nil, trace_ids: nil, max_concurrency: 10,
|
|
161
|
-
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",
|
|
169
|
+
name: nil, code_change_description: Replay::CODE_CHANGE_UNSET, code_change_files: Replay::CODE_CHANGE_UNSET, experiment_group_id: nil, dataset_id: nil, dataset_ids: nil, grader_ids: nil, mock: "marked",
|
|
162
170
|
adapt_inputs: nil, mock_override: nil, db_branch: nil, on_item_start: nil, on_item_finish: nil, on_progress: nil)
|
|
163
171
|
Replay.run(
|
|
164
172
|
self,
|
|
@@ -173,6 +181,7 @@ module Bitfab
|
|
|
173
181
|
code_change_files:,
|
|
174
182
|
experiment_group_id:,
|
|
175
183
|
dataset_id:,
|
|
184
|
+
dataset_ids:,
|
|
176
185
|
grader_ids:,
|
|
177
186
|
mock:,
|
|
178
187
|
adapt_inputs:,
|
data/lib/bitfab/http_client.rb
CHANGED
|
@@ -173,14 +173,17 @@ module Bitfab
|
|
|
173
173
|
# replay runs into a single experiment batch
|
|
174
174
|
# @param name [String, nil] optional display name for the resulting
|
|
175
175
|
# experiment/test run
|
|
176
|
-
# @param
|
|
177
|
-
# runs against
|
|
176
|
+
# @param dataset_ids [Array<String>, nil] optional UUIDs of the datasets this
|
|
177
|
+
# replay runs against. The run replays the union of their traces, graded by
|
|
178
|
+
# the union of their graders, and is attributed to every one of them. A
|
|
179
|
+
# single id travels as datasetId so a new SDK keeps working against a
|
|
180
|
+
# server that predates datasetIds.
|
|
178
181
|
# @param grader_ids [Array<String>, nil] optional UUIDs of graders attached
|
|
179
182
|
# directly to this experiment, graded as the union with the dataset's
|
|
180
183
|
# runnable graders at completion; each must be an active/live grader in the
|
|
181
184
|
# same org and trace function or the server rejects the replay
|
|
182
185
|
def start_replay(trace_function_key, limit, trace_ids: nil, code_change_description: nil,
|
|
183
|
-
code_change_files: nil, experiment_group_id: nil, name: nil, include_db_branch_lease: false,
|
|
186
|
+
code_change_files: nil, experiment_group_id: nil, name: nil, include_db_branch_lease: false, dataset_ids: nil,
|
|
184
187
|
grader_ids: nil, db_branch_settings: nil)
|
|
185
188
|
payload = {
|
|
186
189
|
"traceFunctionKey" => trace_function_key
|
|
@@ -195,7 +198,13 @@ module Bitfab
|
|
|
195
198
|
payload["experimentGroupId"] = experiment_group_id unless experiment_group_id.nil?
|
|
196
199
|
payload["includeDbBranchLease"] = true if include_db_branch_lease
|
|
197
200
|
payload["lazyDbBranchLease"] = true if include_db_branch_lease
|
|
198
|
-
|
|
201
|
+
unless dataset_ids.nil?
|
|
202
|
+
if dataset_ids.length == 1
|
|
203
|
+
payload["datasetId"] = dataset_ids.first
|
|
204
|
+
else
|
|
205
|
+
payload["datasetIds"] = dataset_ids
|
|
206
|
+
end
|
|
207
|
+
end
|
|
199
208
|
payload["graderIds"] = grader_ids unless grader_ids.nil?
|
|
200
209
|
payload["dbBranchSettings"] = db_branch_settings unless db_branch_settings.nil?
|
|
201
210
|
|
data/lib/bitfab/replay.rb
CHANGED
|
@@ -187,7 +187,7 @@ module Bitfab
|
|
|
187
187
|
# @param method_name [Symbol] the method to replay
|
|
188
188
|
# @param trace_function_key [String] the trace function key for this method
|
|
189
189
|
# @param limit [Integer, nil] maximum number of traces to replay (default: 5).
|
|
190
|
-
# Ignored when trace_ids or
|
|
190
|
+
# Ignored when trace_ids or a dataset is passed because either source
|
|
191
191
|
# already determines how many traces replay. Supplying trace_ids also
|
|
192
192
|
# emits a warning.
|
|
193
193
|
# @param trace_ids [Array<String>, nil] optional list of trace IDs to replay (max 100)
|
|
@@ -205,7 +205,15 @@ module Bitfab
|
|
|
205
205
|
# @param experiment_group_id [String, nil] optional UUID grouping multiple
|
|
206
206
|
# replay runs into a single experiment batch
|
|
207
207
|
# @param dataset_id [String, nil] optional UUID of the dataset this replay
|
|
208
|
-
# runs against, stored on the resulting experiment for durable attribution
|
|
208
|
+
# runs against, stored on the resulting experiment for durable attribution;
|
|
209
|
+
# mutually exclusive with dataset_ids. Alone it replays the dataset's full
|
|
210
|
+
# membership, and with trace_ids it replays only those members
|
|
211
|
+
# @param dataset_ids [Array<String>, nil] optional UUIDs of the datasets this
|
|
212
|
+
# replay runs against, for benchmarking one method against several corpora
|
|
213
|
+
# in a single run; mutually exclusive with dataset_id. The run replays the
|
|
214
|
+
# union of their traces, graded by the union of their graders, and is
|
|
215
|
+
# attributed to every one of them. Passing trace_ids alongside it narrows
|
|
216
|
+
# the run to those members
|
|
209
217
|
# @param grader_ids [Array<String>, nil] optional UUIDs of graders attached
|
|
210
218
|
# directly to this experiment, graded as the union with the dataset's
|
|
211
219
|
# runnable graders at completion; each must be an active/live grader in the
|
|
@@ -248,7 +256,7 @@ module Bitfab
|
|
|
248
256
|
# @return [Hash] with :items, :test_run_id, :test_run_url
|
|
249
257
|
def run(client, receiver, method_name, trace_function_key:, limit: nil, trace_ids: nil, name: nil,
|
|
250
258
|
max_concurrency: 10, code_change_description: CODE_CHANGE_UNSET, code_change_files: CODE_CHANGE_UNSET, experiment_group_id: nil,
|
|
251
|
-
dataset_id: nil, grader_ids: nil, mock: "marked",
|
|
259
|
+
dataset_id: nil, dataset_ids: nil, grader_ids: nil, mock: "marked",
|
|
252
260
|
adapt_inputs: nil, mock_override: nil, db_branch: nil, on_item_start: nil, on_item_finish: nil, on_progress: nil)
|
|
253
261
|
unless MOCK_STRATEGIES.include?(mock.to_s)
|
|
254
262
|
raise ArgumentError, "Invalid mock strategy '#{mock}'. Must be one of: #{MOCK_STRATEGIES.join(", ")}"
|
|
@@ -260,10 +268,7 @@ module Bitfab
|
|
|
260
268
|
raise ArgumentError, "trace_ids supports at most 100 trace IDs per replay (got #{trace_ids.length})."
|
|
261
269
|
end
|
|
262
270
|
end
|
|
263
|
-
|
|
264
|
-
raise ArgumentError,
|
|
265
|
-
"trace_ids and dataset_id select different replay sources and cannot be used together."
|
|
266
|
-
end
|
|
271
|
+
resolved_dataset_ids = resolve_dataset_ids(dataset_id, dataset_ids)
|
|
267
272
|
if limit && trace_ids
|
|
268
273
|
warn "Bitfab: limit is ignored when trace_ids is passed: the explicit trace ID list already " \
|
|
269
274
|
"determines how many traces replay."
|
|
@@ -321,7 +326,7 @@ module Bitfab
|
|
|
321
326
|
code_change_files:,
|
|
322
327
|
experiment_group_id:,
|
|
323
328
|
include_db_branch_lease:,
|
|
324
|
-
|
|
329
|
+
dataset_ids: resolved_dataset_ids,
|
|
325
330
|
grader_ids:,
|
|
326
331
|
db_branch_settings: resolved_db_branch_settings
|
|
327
332
|
)
|
|
@@ -472,6 +477,19 @@ module Bitfab
|
|
|
472
477
|
CC_MAX_FILE_BYTES = 500_000
|
|
473
478
|
CC_MAX_TOTAL_BYTES = 2_000_000
|
|
474
479
|
|
|
480
|
+
def resolve_dataset_ids(dataset_id, dataset_ids)
|
|
481
|
+
if dataset_id && dataset_ids
|
|
482
|
+
raise ArgumentError,
|
|
483
|
+
"dataset_id and dataset_ids are the same selector: pass one dataset through dataset_id, " \
|
|
484
|
+
"or several through dataset_ids."
|
|
485
|
+
end
|
|
486
|
+
return [dataset_id] if dataset_id
|
|
487
|
+
return nil if dataset_ids.nil?
|
|
488
|
+
raise ArgumentError, "dataset_ids must contain at least one dataset ID." if dataset_ids.empty?
|
|
489
|
+
|
|
490
|
+
dataset_ids.uniq
|
|
491
|
+
end
|
|
492
|
+
|
|
475
493
|
# Whether the caller asked for database branching. +true+ and a Hash both
|
|
476
494
|
# turn it on; +false+ and +nil+ leave it off. Kept separate from
|
|
477
495
|
# +db_branch_settings+ because +db_branch: true+ enables branching while
|
|
@@ -20,7 +20,7 @@ module Bitfab
|
|
|
20
20
|
class ReplayRegistry
|
|
21
21
|
OPTION_NAMES = %i[
|
|
22
22
|
limit trace_ids name max_concurrency code_change_description
|
|
23
|
-
code_change_files experiment_group_id dataset_id grader_ids mock
|
|
23
|
+
code_change_files experiment_group_id dataset_id dataset_ids grader_ids mock
|
|
24
24
|
mock_override adapt_inputs db_branch
|
|
25
25
|
].freeze
|
|
26
26
|
|
|
@@ -81,8 +81,26 @@ module Bitfab
|
|
|
81
81
|
|
|
82
82
|
# Argument parsing and output for the SDK-owned replay command.
|
|
83
83
|
module ReplayCli
|
|
84
|
+
MAX_PINNED_TRACE_IDS = 100
|
|
85
|
+
|
|
84
86
|
module_function
|
|
85
87
|
|
|
88
|
+
def pinned_dataset_members(client, dataset_ids, limit)
|
|
89
|
+
members = dataset_ids.flat_map { |dataset_id|
|
|
90
|
+
client.datasets.list_traces(dataset_id).fetch("traceIds")
|
|
91
|
+
}.uniq.sort
|
|
92
|
+
return nil if limit >= members.length
|
|
93
|
+
|
|
94
|
+
if limit > MAX_PINNED_TRACE_IDS
|
|
95
|
+
raise ArgumentError,
|
|
96
|
+
"Bounding a dataset replay to #{limit} names one trace ID per replayed item, and " \
|
|
97
|
+
"a replay accepts at most #{MAX_PINNED_TRACE_IDS}. Drop the limit to replay " \
|
|
98
|
+
"every selected dataset in full."
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
members.first(limit)
|
|
102
|
+
end
|
|
103
|
+
|
|
86
104
|
def run(registry, argv: ARGV, stdout: $stdout, stderr: $stderr)
|
|
87
105
|
args = parse(registry, argv.dup)
|
|
88
106
|
registration = registry.fetch(args.fetch(:pipeline))
|
|
@@ -97,29 +115,39 @@ module Bitfab
|
|
|
97
115
|
options.merge!(dynamic_options)
|
|
98
116
|
end
|
|
99
117
|
|
|
100
|
-
|
|
118
|
+
selected_dataset_ids = registry_dataset_ids(options)
|
|
119
|
+
options.delete(:dataset_id)
|
|
120
|
+
options.delete(:dataset_ids)
|
|
121
|
+
options[:dataset_ids] = selected_dataset_ids if selected_dataset_ids
|
|
122
|
+
|
|
123
|
+
if options[:trace_ids] && selected_dataset_ids
|
|
101
124
|
raise ArgumentError,
|
|
102
|
-
"Replay registry options trace_ids and
|
|
125
|
+
"Replay registry options trace_ids and dataset_ids select different sources and cannot be used together."
|
|
103
126
|
end
|
|
104
127
|
|
|
105
128
|
if args[:trace_ids]
|
|
106
|
-
options.delete(:
|
|
107
|
-
options.delete(:dataset_id)
|
|
129
|
+
options.delete(:dataset_ids)
|
|
108
130
|
options[:trace_ids] = args[:trace_ids]
|
|
109
|
-
elsif args[:
|
|
110
|
-
options.delete(:trace_ids)
|
|
111
|
-
options.delete(:limit)
|
|
112
|
-
elsif args[:limit]
|
|
131
|
+
elsif args[:dataset_ids]
|
|
113
132
|
options.delete(:trace_ids)
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
bound = args[:limit] || options[:limit]
|
|
136
|
+
options.delete(:limit)
|
|
137
|
+
bounded_dataset_ids = args[:dataset_ids] || options[:dataset_ids]
|
|
138
|
+
|
|
139
|
+
if options[:trace_ids]
|
|
140
|
+
options[:trace_ids] = options[:trace_ids].first(bound) if bound
|
|
141
|
+
elsif bounded_dataset_ids
|
|
142
|
+
if bound
|
|
143
|
+
pinned = pinned_dataset_members(registration.client, bounded_dataset_ids, bound)
|
|
144
|
+
options[:trace_ids] = pinned if pinned
|
|
145
|
+
end
|
|
118
146
|
else
|
|
119
|
-
options[:limit] =
|
|
147
|
+
options[:limit] = bound || 10
|
|
120
148
|
end
|
|
121
149
|
|
|
122
|
-
%i[name max_concurrency experiment_group_id
|
|
150
|
+
%i[name max_concurrency experiment_group_id dataset_ids grader_ids mock].each do |key|
|
|
123
151
|
options[key] = args[key] unless args[key].nil?
|
|
124
152
|
end
|
|
125
153
|
|
|
@@ -145,8 +173,7 @@ module Bitfab
|
|
|
145
173
|
options[:on_item_start] = reporter
|
|
146
174
|
options[:on_item_finish] = reporter
|
|
147
175
|
|
|
148
|
-
|
|
149
|
-
stderr.puts "[replay] Replaying #{count} traces from \"#{registration.trace_function_key}\"..."
|
|
176
|
+
stderr.puts "[replay] Replaying #{describe_selection(options)} from \"#{registration.trace_function_key}\"..."
|
|
150
177
|
|
|
151
178
|
result = begin
|
|
152
179
|
registration.client.replay(
|
|
@@ -175,7 +202,10 @@ module Bitfab
|
|
|
175
202
|
args = {}
|
|
176
203
|
parser = OptionParser.new do |options|
|
|
177
204
|
options.banner = "Usage: bitfab-replay <#{registry.names.join("|")}> [options]"
|
|
178
|
-
options.on("--limit N", Integer
|
|
205
|
+
options.on("--limit N", Integer,
|
|
206
|
+
"How many traces to replay. It bounds a trace ID or dataset selection instead of replacing it") do |value|
|
|
207
|
+
args[:limit] = positive_integer("--limit", value)
|
|
208
|
+
end
|
|
179
209
|
options.on("--trace-ids IDS") { |value| args[:trace_ids] = comma_separated("--trace-ids", value) }
|
|
180
210
|
options.on("--name NAME") { |value| args[:name] = value }
|
|
181
211
|
options.on("--concurrency N", Integer) do |value|
|
|
@@ -186,7 +216,7 @@ module Bitfab
|
|
|
186
216
|
end
|
|
187
217
|
options.on("--code-change PATH") { |value| args[:code_change] = value }
|
|
188
218
|
options.on("--experiment-group-id UUID") { |value| args[:experiment_group_id] = value }
|
|
189
|
-
options.on("--dataset-id
|
|
219
|
+
options.on("--dataset-ids IDS", "--dataset-id IDS") { |value| args[:dataset_ids] = comma_separated("--dataset-ids", value) }
|
|
190
220
|
options.on("--grader-ids IDS") { |value| args[:grader_ids] = comma_separated("--grader-ids", value) }
|
|
191
221
|
options.on("--mock STRATEGY", %w[none all marked]) { |value| args[:mock] = value }
|
|
192
222
|
options.on("--db-branch") { args[:db_branch] = true }
|
|
@@ -196,9 +226,9 @@ module Bitfab
|
|
|
196
226
|
options.on("--param NAME=VALUE") { |value| (args[:param] ||= []) << value }
|
|
197
227
|
end
|
|
198
228
|
parser.parse!(argv)
|
|
199
|
-
if args[:trace_ids] && args[:
|
|
229
|
+
if args[:trace_ids] && args[:dataset_ids]
|
|
200
230
|
raise OptionParser::InvalidArgument,
|
|
201
|
-
"--trace-ids and --dataset-
|
|
231
|
+
"--trace-ids and --dataset-ids select different replay sources and cannot be used together"
|
|
202
232
|
end
|
|
203
233
|
if args[:code_change] && args[:no_code_change]
|
|
204
234
|
raise OptionParser::InvalidArgument, "--code-change and --no-code-change cannot be used together"
|
|
@@ -210,6 +240,26 @@ module Bitfab
|
|
|
210
240
|
args.merge(pipeline:)
|
|
211
241
|
end
|
|
212
242
|
|
|
243
|
+
def registry_dataset_ids(options)
|
|
244
|
+
dataset_id = options[:dataset_id]
|
|
245
|
+
dataset_ids = options[:dataset_ids]
|
|
246
|
+
if dataset_id && dataset_ids
|
|
247
|
+
raise ArgumentError,
|
|
248
|
+
"Replay registry options dataset_id and dataset_ids are the same selector: set one of them."
|
|
249
|
+
end
|
|
250
|
+
return [dataset_id] if dataset_id
|
|
251
|
+
|
|
252
|
+
dataset_ids
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def describe_selection(options)
|
|
256
|
+
return "#{options[:trace_ids].length} traces" if options[:trace_ids]
|
|
257
|
+
return "#{options[:limit]} traces" if options[:limit]
|
|
258
|
+
|
|
259
|
+
dataset_count = options[:dataset_ids]&.length || 1
|
|
260
|
+
(dataset_count > 1) ? "#{dataset_count} datasets' traces" : "dataset traces"
|
|
261
|
+
end
|
|
262
|
+
|
|
213
263
|
def positive_integer(flag, value)
|
|
214
264
|
raise OptionParser::InvalidArgument, "#{flag} must be a positive integer" if value < 1
|
|
215
265
|
|
data/lib/bitfab/version.rb
CHANGED