@bitfab/sdk 0.36.9 → 0.36.10

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.
@@ -304,7 +304,7 @@ function encodeRequestBody(body) {
304
304
  }
305
305
 
306
306
  // src/version.generated.ts
307
- var __version__ = "0.36.9";
307
+ var __version__ = "0.36.10";
308
308
 
309
309
  // src/constants.ts
310
310
  var DEFAULT_SERVICE_URL = "https://bitfab.ai";
@@ -1503,6 +1503,10 @@ var HttpClient = class {
1503
1503
  ...error instanceof BitfabError && error.retryAfterMs !== void 0 ? { retryAfterMs: error.retryAfterMs } : {}
1504
1504
  });
1505
1505
  }
1506
+ const serverTraceIds = asPayloadRecord(response?.traceIds);
1507
+ if (serverTraceIds !== void 0) {
1508
+ this.recordServerTraceIds(serverTraceIds);
1509
+ }
1506
1510
  const partialSuccess = asPayloadRecord(response?.partialSuccess);
1507
1511
  const rejected = partialSuccess?.rejectedSpans;
1508
1512
  if (rejected !== void 0 && rejected !== "0" && rejected !== 0) {
@@ -1527,6 +1531,14 @@ var HttpClient = class {
1527
1531
  }
1528
1532
  }
1529
1533
  }
1534
+ /**
1535
+ * The server's assigned `traces.id` for a tracked trace if it has already
1536
+ * been read back off an ingest response, without stopping tracking. Lets a
1537
+ * replay surface the id mid-run for items whose spans already landed.
1538
+ */
1539
+ peekServerTraceId(traceId) {
1540
+ return this.traceDeliveries.get(traceId)?.serverTraceId;
1541
+ }
1530
1542
  /** Whether any tracked trace has had its closing carrier submitted. */
1531
1543
  hasClosedDeliveries(traceIds) {
1532
1544
  return traceIds.some((traceId) => this.traceDeliveries.get(traceId)?.closed);
@@ -1553,7 +1565,8 @@ var HttpClient = class {
1553
1565
  closed: delivery.closed,
1554
1566
  delivered: delivery.closingAcked && [...delivery.submittedSpanIds].every(
1555
1567
  (spanId) => delivery.ackedSpanIds.has(spanId)
1556
- )
1568
+ ),
1569
+ serverTraceId: delivery.serverTraceId
1557
1570
  };
1558
1571
  }
1559
1572
  return reports;
@@ -1582,6 +1595,23 @@ var HttpClient = class {
1582
1595
  * delivered ref is proof its row exists: the same fact the replay status
1583
1596
  * endpoint would report, already in hand.
1584
1597
  */
1598
+ /**
1599
+ * Record the server's assigned `traces.id` for each tracked source trace,
1600
+ * read back from the OTLP ingest response. Keyed by source trace id, the same
1601
+ * key the delivery ledger uses. Untracked ids are ignored.
1602
+ */
1603
+ recordServerTraceIds(map) {
1604
+ for (const [sourceTraceId, serverTraceId] of Object.entries(map)) {
1605
+ if (typeof serverTraceId !== "string") {
1606
+ continue;
1607
+ }
1608
+ const delivery = this.traceDeliveries.get(sourceTraceId);
1609
+ if (delivery === void 0) {
1610
+ continue;
1611
+ }
1612
+ delivery.serverTraceId = serverTraceId;
1613
+ }
1614
+ }
1585
1615
  recordDeliveredCarriers(refs) {
1586
1616
  for (const ref of refs) {
1587
1617
  const delivery = this.traceDeliveries.get(ref.traceId);
@@ -2511,13 +2541,17 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
2511
2541
  }
2512
2542
  if (!httpClient.hasClosedDeliveries(replayedTraceIds)) {
2513
2543
  httpClient.takeTraceDeliveries(replayedTraceIds);
2514
- return;
2544
+ return {};
2515
2545
  }
2516
2546
  const flushed = await flushTraces(REPLAY_PERSISTENCE_TIMEOUT_MS);
2517
2547
  const deliveries = httpClient.takeTraceDeliveries(replayedTraceIds);
2518
2548
  const expectedSpanCounts = {};
2549
+ const readBackTraceIds = {};
2519
2550
  let allDelivered = true;
2520
2551
  for (const [traceId, delivery] of Object.entries(deliveries)) {
2552
+ if (delivery.serverTraceId !== void 0) {
2553
+ readBackTraceIds[traceId] = delivery.serverTraceId;
2554
+ }
2521
2555
  if (!delivery.closed) {
2522
2556
  continue;
2523
2557
  }
@@ -2525,7 +2559,7 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
2525
2559
  allDelivered = allDelivered && delivery.delivered;
2526
2560
  }
2527
2561
  if (allDelivered) {
2528
- return;
2562
+ return readBackTraceIds;
2529
2563
  }
2530
2564
  const deadline = Date.now() + REPLAY_PERSISTENCE_TIMEOUT_MS;
2531
2565
  let missing = Object.keys(expectedSpanCounts).length;
@@ -2539,7 +2573,7 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
2539
2573
  (traceId) => ready[traceId] === void 0
2540
2574
  ).length;
2541
2575
  if (missing === 0) {
2542
- return;
2576
+ return readBackTraceIds;
2543
2577
  }
2544
2578
  if (Date.now() >= deadline) {
2545
2579
  break;
@@ -2567,7 +2601,7 @@ async function mapWithConcurrency2(tasks, maxConcurrency, onSettled, onStarted)
2567
2601
  onStarted?.(index);
2568
2602
  const result = await tasks[index]();
2569
2603
  results[index] = result;
2570
- onSettled?.(result, index);
2604
+ await onSettled?.(result, index);
2571
2605
  }
2572
2606
  }
2573
2607
  const workers = Array.from(
@@ -2657,10 +2691,36 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2657
2691
  let started = 0;
2658
2692
  let succeeded = 0;
2659
2693
  let errored = 0;
2694
+ let flushInFlight = null;
2695
+ let flushPending = false;
2696
+ const flushFinishedItemTrace = () => {
2697
+ flushPending = true;
2698
+ if (!flushInFlight) {
2699
+ flushInFlight = (async () => {
2700
+ try {
2701
+ while (flushPending) {
2702
+ flushPending = false;
2703
+ await httpClient.settleDeferredWork(REPLAY_PERSISTENCE_TIMEOUT_MS);
2704
+ await flushTraces(REPLAY_PERSISTENCE_TIMEOUT_MS);
2705
+ }
2706
+ } finally {
2707
+ flushInFlight = null;
2708
+ }
2709
+ })();
2710
+ }
2711
+ return flushInFlight;
2712
+ };
2660
2713
  const resultItems = await mapWithConcurrency2(
2661
2714
  tasks,
2662
2715
  maxConcurrency,
2663
- (item) => {
2716
+ async (item, index) => {
2717
+ let serverTraceId = null;
2718
+ try {
2719
+ await flushFinishedItemTrace();
2720
+ serverTraceId = httpClient.peekServerTraceId(replayedTraceIds[index]) ?? null;
2721
+ } catch {
2722
+ }
2723
+ item.traceId = serverTraceId;
2664
2724
  completed += 1;
2665
2725
  if (item.error === null) {
2666
2726
  succeeded += 1;
@@ -2675,11 +2735,12 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2675
2735
  succeeded,
2676
2736
  errored,
2677
2737
  item: {
2678
- // The server replay trace id isn't known until completeReplay runs
2679
- // (below), so it can't be reported mid-run and we never emit the
2680
- // client-side placeholder. originalTraceId (the historical trace)
2681
- // is known now and is what a UI keys on to identify what settled.
2682
- traceId: null,
2738
+ // The server's assigned traces.id, read back off the ingest
2739
+ // response and surfaced as this item finishes. Null only if the
2740
+ // per-item flush could not confirm delivery in time; the end-of-run
2741
+ // barrier then fills the returned ReplayItem. The client-side
2742
+ // placeholder is never surfaced.
2743
+ traceId: serverTraceId,
2683
2744
  originalTraceId: item.originalTraceId ?? null,
2684
2745
  originalSpanId: item.originalSpanId ?? null,
2685
2746
  // Deprecated aliases for originalTraceId/originalSpanId.
@@ -2725,12 +2786,19 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2725
2786
  }
2726
2787
  } : void 0
2727
2788
  );
2728
- await preserveReplayFailure(
2789
+ const deliveredTraceIds = await preserveReplayFailure(
2729
2790
  () => waitForReplayPersistence(httpClient, testRunId, replayedTraceIds),
2730
2791
  resultItems,
2731
2792
  testRunId,
2732
2793
  fullTestRunUrl
2733
2794
  );
2795
+ for (let index = 0; index < resultItems.length; index += 1) {
2796
+ const localId = replayedTraceIds[index];
2797
+ const readBack = localId ? deliveredTraceIds[localId] : void 0;
2798
+ if (readBack !== void 0) {
2799
+ resultItems[index].traceId = readBack;
2800
+ }
2801
+ }
2734
2802
  const completeResult = await preserveReplayFailure(
2735
2803
  () => httpClient.completeReplay(testRunId),
2736
2804
  resultItems,
@@ -2746,7 +2814,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2746
2814
  const item = resultItems[index];
2747
2815
  const localId = replayedTraceIds[index];
2748
2816
  const mapped = localId ? serverTraceIds[localId] : void 0;
2749
- item.traceId = mapped ?? null;
2817
+ item.traceId = item.traceId ?? mapped ?? null;
2750
2818
  if (item.error === null) {
2751
2819
  completedCount += 1;
2752
2820
  if (mapped === void 0) {
@@ -2855,4 +2923,4 @@ export {
2855
2923
  sleepForReplayPersistence,
2856
2924
  replay
2857
2925
  };
2858
- //# sourceMappingURL=chunk-MBKY42QC.js.map
2926
+ //# sourceMappingURL=chunk-AAMRJGZJ.js.map