bitfab 0.41.0 → 0.42.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.
package/dist/index.cjs CHANGED
@@ -51,7 +51,7 @@ var __version__, __packageName__;
51
51
  var init_version_generated = __esm({
52
52
  "src/version.generated.ts"() {
53
53
  "use strict";
54
- __version__ = "0.41.0";
54
+ __version__ = "0.42.0";
55
55
  __packageName__ = "bitfab";
56
56
  }
57
57
  });
@@ -1346,7 +1346,7 @@ function sourceTraceIdOf(payload) {
1346
1346
  const id = rawTrace?.id;
1347
1347
  return typeof id === "string" ? id : void 0;
1348
1348
  }
1349
- var REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS, OTLP_TRACES_ENDPOINT, RETRYABLE_STATUSES, EXIT_FLUSH_TIMEOUT_MS, DEFAULT_LIFECYCLE_TIMEOUT_MS2, pendingTracePromises, carrierSeq, HttpClient;
1349
+ var REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS, REPLAY_COMPLETE_REQUEST_TIMEOUT_MS, OTLP_TRACES_ENDPOINT, RETRYABLE_STATUSES, EXIT_FLUSH_TIMEOUT_MS, DEFAULT_LIFECYCLE_TIMEOUT_MS2, pendingTracePromises, carrierSeq, HttpClient;
1350
1350
  var init_http = __esm({
1351
1351
  "src/http.ts"() {
1352
1352
  "use strict";
@@ -1360,6 +1360,7 @@ var init_http = __esm({
1360
1360
  init_unrefTimer();
1361
1361
  init_warnOnce();
1362
1362
  REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS = 3e5;
1363
+ REPLAY_COMPLETE_REQUEST_TIMEOUT_MS = 12e4;
1363
1364
  OTLP_TRACES_ENDPOINT = "/api/sdk/otel/v1/traces";
1364
1365
  RETRYABLE_STATUSES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
1365
1366
  EXIT_FLUSH_TIMEOUT_MS = 5e3;
@@ -1849,7 +1850,7 @@ var init_http = __esm({
1849
1850
  * Start a replay session by fetching historical traces.
1850
1851
  * Blocking call - creates a test run and returns lightweight item references.
1851
1852
  */
1852
- async startReplay(traceFunctionKey, limit, traceIds, name, codeChangeDescription, codeChangeFiles, includeDbBranchLease, experimentGroupId, datasetId, graderIds, dbBranchSettings) {
1853
+ async startReplay(traceFunctionKey, limit, traceIds, name, codeChangeDescription, codeChangeFiles, includeDbBranchLease, experimentGroupId, datasetId, graderIds, dbBranchSettings, attempts) {
1853
1854
  const payload = { traceFunctionKey };
1854
1855
  if (limit !== void 0) {
1855
1856
  payload.limit = limit;
@@ -1882,6 +1883,9 @@ var init_http = __esm({
1882
1883
  if (dbBranchSettings !== void 0) {
1883
1884
  payload.dbBranchSettings = dbBranchSettings;
1884
1885
  }
1886
+ if (attempts !== void 0 && attempts > 1) {
1887
+ payload.attempts = attempts;
1888
+ }
1885
1889
  const timeout = includeDbBranchLease ? REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS : 3e4;
1886
1890
  return this.request("/api/sdk/replay/start", payload, {
1887
1891
  timeout
@@ -1997,7 +2001,7 @@ var init_http = __esm({
1997
2001
  return this.request(
1998
2002
  "/api/sdk/replay/complete",
1999
2003
  { testRunId },
2000
- { timeout: 3e4 }
2004
+ { timeout: REPLAY_COMPLETE_REQUEST_TIMEOUT_MS }
2001
2005
  );
2002
2006
  }
2003
2007
  /**
@@ -2006,10 +2010,15 @@ var init_http = __esm({
2006
2010
  * snapshot + preview branch and polls operations to readiness, which
2007
2011
  * can take seconds.
2008
2012
  */
2009
- async resolveDbBranchLease(testRunId, traceId, dbBranchSettings) {
2013
+ async resolveDbBranchLease(testRunId, traceId, dbBranchSettings, attempt) {
2010
2014
  return this.request(
2011
2015
  "/api/sdk/replay/resolveDbBranchLease",
2012
- { testRunId, traceId, dbBranchSettings },
2016
+ {
2017
+ testRunId,
2018
+ traceId,
2019
+ dbBranchSettings,
2020
+ ...attempt !== void 0 && attempt > 0 ? { attempt } : {}
2021
+ },
2013
2022
  { timeout: REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS }
2014
2023
  );
2015
2024
  }
@@ -2445,6 +2454,23 @@ __export(replay_exports, {
2445
2454
  sleepForReplayPersistence: () => sleepForReplayPersistence,
2446
2455
  waitForReplayPersistence: () => waitForReplayPersistence
2447
2456
  });
2457
+ function expandReplayWork(serverItems, attempts) {
2458
+ return Array.from(
2459
+ { length: attempts },
2460
+ (_, attempt) => serverItems.map((serverItem) => ({ serverItem, attempt }))
2461
+ ).flat();
2462
+ }
2463
+ function resolveAttempts(attempts) {
2464
+ if (attempts === void 0) {
2465
+ return 1;
2466
+ }
2467
+ if (!Number.isInteger(attempts) || attempts < 1 || attempts > MAX_REPLAY_ATTEMPTS) {
2468
+ throw new BitfabError(
2469
+ `attempts must be an integer from 1 to ${MAX_REPLAY_ATTEMPTS} (got ${attempts}).`
2470
+ );
2471
+ }
2472
+ return attempts;
2473
+ }
2448
2474
  function dbBranchEnabled(dbBranch) {
2449
2475
  return dbBranch !== void 0 && dbBranch !== false;
2450
2476
  }
@@ -2568,7 +2594,7 @@ function buildMockTree(rootNode) {
2568
2594
  }
2569
2595
  return { spans };
2570
2596
  }
2571
- async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy, resolvedOverrides, replayedTraceId, includeDbBranchLease, dbBranchSettings, adaptInputs, dryRun) {
2597
+ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy, resolvedOverrides, replayedTraceId, attempt, includeDbBranchLease, dbBranchSettings, adaptInputs, dryRun) {
2572
2598
  let lease = includeDbBranchLease ? serverItem.dbBranchLease : void 0;
2573
2599
  let leaseError = includeDbBranchLease ? serverItem.dbBranchLeaseError : void 0;
2574
2600
  let dbSnapshotRef = serverItem.dbSnapshotRef;
@@ -2590,7 +2616,8 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
2590
2616
  resolved = await httpClient.resolveDbBranchLease(
2591
2617
  testRunId,
2592
2618
  originalTraceId,
2593
- dbBranchSettings
2619
+ dbBranchSettings,
2620
+ attempt
2594
2621
  );
2595
2622
  } catch (cause) {
2596
2623
  throw new DbBranchReplayError(
@@ -2670,6 +2697,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
2670
2697
  originalSpanId,
2671
2698
  sourceTraceId: originalTraceId,
2672
2699
  sourceSpanId: originalSpanId,
2700
+ attempt,
2673
2701
  input: inputs,
2674
2702
  result: void 0,
2675
2703
  originalOutput,
@@ -2698,6 +2726,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
2698
2726
  inputSourceSpanId: span.id,
2699
2727
  inputSourceTraceId: span.externalTraceId,
2700
2728
  sourceBitfabTraceId: originalTraceId,
2729
+ replayAttempt: attempt,
2701
2730
  mockTree,
2702
2731
  callCounters: mockTree ? /* @__PURE__ */ new Map() : void 0,
2703
2732
  mockStrategy,
@@ -2749,6 +2778,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
2749
2778
  // Deprecated aliases for originalTraceId/originalSpanId.
2750
2779
  sourceTraceId: originalTraceId,
2751
2780
  sourceSpanId: originalSpanId,
2781
+ attempt,
2752
2782
  input: inputs,
2753
2783
  result,
2754
2784
  originalOutput,
@@ -2877,6 +2907,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2877
2907
  } catch {
2878
2908
  }
2879
2909
  }
2910
+ const attempts = resolveAttempts(options?.attempts);
2880
2911
  await replayContextReady;
2881
2912
  let codeChangeDescription = options?.codeChangeDescription;
2882
2913
  let codeChangeFiles = options?.codeChangeFiles;
@@ -2909,7 +2940,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2909
2940
  options?.experimentGroupId,
2910
2941
  options?.datasetId,
2911
2942
  options?.graderIds,
2912
- resolveDbBranchSettings(options?.dbBranch)
2943
+ resolveDbBranchSettings(options?.dbBranch),
2944
+ attempts
2913
2945
  );
2914
2946
  if (serverItems.length === 0) {
2915
2947
  try {
@@ -2926,10 +2958,11 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2926
2958
  ...normalizeMockOverrides(options?.mockOverride),
2927
2959
  ...registeredOverrides
2928
2960
  ];
2929
- const replayedTraceIds = serverItems.map(() => randomUuid());
2961
+ const workItems = expandReplayWork(serverItems, attempts);
2962
+ const replayedTraceIds = workItems.map(() => randomUuid());
2930
2963
  httpClient.trackTraceDeliveries(replayedTraceIds);
2931
- const tasks = serverItems.map(
2932
- (serverItem, index) => () => processItem(
2964
+ const tasks = workItems.map(
2965
+ ({ serverItem, attempt }, index) => () => processItem(
2933
2966
  httpClient,
2934
2967
  serverItem,
2935
2968
  fn,
@@ -2937,6 +2970,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2937
2970
  mockStrategy,
2938
2971
  resolvedOverrides,
2939
2972
  replayedTraceIds[index],
2973
+ attempt,
2940
2974
  dbBranchEnabled(options?.dbBranch) && options?.dryRun !== true,
2941
2975
  resolveDbBranchSettings(options?.dbBranch),
2942
2976
  options?.adaptInputs,
@@ -3004,6 +3038,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
3004
3038
  // Deprecated aliases for originalTraceId/originalSpanId.
3005
3039
  sourceTraceId: item.originalTraceId ?? null,
3006
3040
  sourceSpanId: item.originalSpanId ?? null,
3041
+ attempt: item.attempt,
3007
3042
  input: item.input,
3008
3043
  result: item.result,
3009
3044
  originalOutput: item.originalOutput,
@@ -3025,7 +3060,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
3025
3060
  },
3026
3061
  options?.onItemStart ? (index) => {
3027
3062
  started += 1;
3028
- const serverItem = serverItems[index];
3063
+ const { serverItem, attempt } = workItems[index];
3029
3064
  const originalTraceId = serverItem.originalTraceId ?? serverItem.sourceTraceId;
3030
3065
  const originalSpanId = serverItem.originalSpanId ?? serverItem.sourceSpanId;
3031
3066
  try {
@@ -3041,7 +3076,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
3041
3076
  originalTraceId,
3042
3077
  originalSpanId,
3043
3078
  sourceTraceId: originalTraceId,
3044
- sourceSpanId: originalSpanId
3079
+ sourceSpanId: originalSpanId,
3080
+ attempt
3045
3081
  }
3046
3082
  });
3047
3083
  } catch {
@@ -3053,7 +3089,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
3053
3089
  const dryResult = {
3054
3090
  items: resultItems,
3055
3091
  testRunId,
3056
- testRunUrl: fullTestRunUrl
3092
+ testRunUrl: fullTestRunUrl,
3093
+ attempts
3057
3094
  };
3058
3095
  await writeReplayResultFile(dryResult);
3059
3096
  return dryResult;
@@ -3122,7 +3159,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
3122
3159
  const result = {
3123
3160
  items: resultItems,
3124
3161
  testRunId,
3125
- testRunUrl: fullTestRunUrl
3162
+ testRunUrl: fullTestRunUrl,
3163
+ attempts
3126
3164
  };
3127
3165
  await writeReplayResultFile(result);
3128
3166
  if (!options?.onItemFinish) {
@@ -3163,7 +3201,7 @@ async function writeReplayResultFile(result) {
3163
3201
  }
3164
3202
  }
3165
3203
  }
3166
- var REPLAY_PERSISTENCE_TIMEOUT_MS, BITFAB_PROGRESS_PREFIX, ReplayError, DbBranchReplayError;
3204
+ var REPLAY_PERSISTENCE_TIMEOUT_MS, MAX_REPLAY_ATTEMPTS, BITFAB_PROGRESS_PREFIX, ReplayError, DbBranchReplayError;
3167
3205
  var init_replay = __esm({
3168
3206
  "src/replay.ts"() {
3169
3207
  "use strict";
@@ -3175,6 +3213,7 @@ var init_replay = __esm({
3175
3213
  init_replayContext();
3176
3214
  init_serialize();
3177
3215
  REPLAY_PERSISTENCE_TIMEOUT_MS = 3e4;
3216
+ MAX_REPLAY_ATTEMPTS = 100;
3178
3217
  BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
3179
3218
  ReplayError = class extends BitfabError {
3180
3219
  constructor(message, items, testRunId, testRunUrl, cause) {
@@ -7021,6 +7060,9 @@ var Bitfab = class {
7021
7060
  ...replayCtxAtStart?.inputSourceTraceId && {
7022
7061
  inputSourceTraceId: replayCtxAtStart.inputSourceTraceId
7023
7062
  },
7063
+ ...replayCtxAtStart?.replayAttempt !== void 0 && {
7064
+ replayAttempt: replayCtxAtStart.replayAttempt
7065
+ },
7024
7066
  dbSnapshotRef
7025
7067
  });
7026
7068
  registeredTraceId = traceId;
@@ -7071,6 +7113,7 @@ var Bitfab = class {
7071
7113
  contexts: traceState?.contexts ?? [],
7072
7114
  testRunId: traceState?.testRunId,
7073
7115
  inputSourceTraceId: traceState?.inputSourceTraceId,
7116
+ replayAttempt: traceState?.replayAttempt,
7074
7117
  dbSnapshotRef: traceState?.dbSnapshotRef,
7075
7118
  dropped: traceState?.dropped,
7076
7119
  ingestionType: traceState?.ingestionType,
@@ -7468,6 +7511,9 @@ var Bitfab = class {
7468
7511
  if (params.inputSourceTraceId) {
7469
7512
  rawTrace.input_source_trace_id = params.inputSourceTraceId;
7470
7513
  }
7514
+ if (params.replayAttempt !== void 0) {
7515
+ rawTrace.replay_attempt = params.replayAttempt;
7516
+ }
7471
7517
  if (params.dbSnapshotRef) {
7472
7518
  rawTrace.db_snapshot_ref = params.dbSnapshotRef;
7473
7519
  }