@cadenza.io/service 2.17.4 → 2.17.5

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.mjs CHANGED
@@ -1793,12 +1793,14 @@ var ServiceRegistry = class _ServiceRegistry {
1793
1793
  this.useSocket ? "socket" : "rest"
1794
1794
  ) : void 0;
1795
1795
  const message = error instanceof Error ? error.message : String(error);
1796
+ const diagnostics = error && typeof error === "object" && "runtimeStatusFallback" in error && error.runtimeStatusFallback && typeof error.runtimeStatusFallback === "object" ? error.runtimeStatusFallback : void 0;
1796
1797
  CadenzaService.log(
1797
1798
  "Runtime status fallback inquiry failed.",
1798
1799
  {
1799
1800
  serviceName,
1800
1801
  serviceInstanceId,
1801
- error: message
1802
+ error: message,
1803
+ diagnostics
1802
1804
  },
1803
1805
  "warning"
1804
1806
  );
@@ -2288,6 +2290,66 @@ var ServiceRegistry = class _ServiceRegistry {
2288
2290
  }
2289
2291
  return this.getInstance(this.serviceName, this.serviceInstanceId);
2290
2292
  }
2293
+ summarizeTransportForDebug(transport) {
2294
+ if (!transport) {
2295
+ return void 0;
2296
+ }
2297
+ return {
2298
+ uuid: transport.uuid,
2299
+ role: transport.role,
2300
+ origin: transport.origin,
2301
+ protocols: transport.protocols,
2302
+ clientCreated: transport.clientCreated
2303
+ };
2304
+ }
2305
+ summarizeInstanceForRuntimeStatusFallback(instance) {
2306
+ return {
2307
+ exists: Boolean(instance),
2308
+ runtimeState: instance?.runtimeState,
2309
+ acceptingWork: instance?.acceptingWork,
2310
+ reportedAt: instance?.reportedAt ?? null,
2311
+ isDatabase: instance?.isDatabase,
2312
+ isFrontend: instance?.isFrontend,
2313
+ transports: (instance?.transports ?? []).map((transport) => ({
2314
+ uuid: transport.uuid,
2315
+ role: transport.role,
2316
+ origin: transport.origin,
2317
+ protocols: transport.protocols,
2318
+ clientCreated: transport.clientCreated
2319
+ }))
2320
+ };
2321
+ }
2322
+ summarizeRuntimeStatusInquiryReports(inquiryResult) {
2323
+ const reports = Array.isArray(inquiryResult.runtimeStatusReports) ? inquiryResult.runtimeStatusReports : [];
2324
+ return reports.map((candidate) => {
2325
+ const normalized = this.normalizeRuntimeStatusReport(candidate);
2326
+ if (normalized) {
2327
+ return {
2328
+ serviceName: normalized.serviceName,
2329
+ serviceInstanceId: normalized.serviceInstanceId,
2330
+ transportId: normalized.transportId,
2331
+ state: normalized.state,
2332
+ acceptingWork: normalized.acceptingWork,
2333
+ reportedAt: normalized.reportedAt
2334
+ };
2335
+ }
2336
+ const raw = candidate && typeof candidate === "object" ? candidate : {};
2337
+ const rawState = raw.state === "healthy" || raw.state === "degraded" || raw.state === "overloaded" || raw.state === "unavailable" ? raw.state : void 0;
2338
+ return {
2339
+ serviceName: typeof raw.serviceName === "string" ? raw.serviceName : typeof raw.__serviceName === "string" ? raw.__serviceName : void 0,
2340
+ serviceInstanceId: typeof raw.serviceInstanceId === "string" ? raw.serviceInstanceId : typeof raw.__serviceInstanceId === "string" ? raw.__serviceInstanceId : void 0,
2341
+ transportId: typeof raw.transportId === "string" ? raw.transportId : typeof raw.serviceTransportId === "string" ? raw.serviceTransportId : void 0,
2342
+ state: rawState,
2343
+ acceptingWork: typeof raw.acceptingWork === "boolean" ? raw.acceptingWork : void 0,
2344
+ reportedAt: typeof raw.reportedAt === "string" ? raw.reportedAt : void 0
2345
+ };
2346
+ });
2347
+ }
2348
+ createRuntimeStatusFallbackError(message, diagnostics) {
2349
+ return Object.assign(new Error(message), {
2350
+ runtimeStatusFallback: diagnostics
2351
+ });
2352
+ }
2291
2353
  resolveLocalStatusCheck(ctx = {}) {
2292
2354
  if (!this.serviceName) {
2293
2355
  return {
@@ -2607,32 +2669,48 @@ var ServiceRegistry = class _ServiceRegistry {
2607
2669
  }
2608
2670
  async resolveRuntimeStatusFallbackInquiry(serviceName, serviceInstanceId, options = {}) {
2609
2671
  const instance = this.getInstance(serviceName, serviceInstanceId);
2610
- if (instance) {
2611
- const directReport = await this.requestRuntimeStatusViaRest(
2612
- instance,
2613
- serviceName,
2614
- serviceInstanceId
2615
- );
2616
- if (directReport) {
2617
- if (!this.applyRuntimeStatusReport(directReport)) {
2618
- throw new Error(
2619
- `No tracked instance for runtime fallback ${serviceName}/${serviceInstanceId}`
2620
- );
2621
- }
2622
- this.lastHeartbeatAtByInstance.set(serviceInstanceId, Date.now());
2623
- this.missedHeartbeatsByInstance.set(serviceInstanceId, 0);
2624
- return {
2625
- report: directReport,
2626
- inquiryMeta: {
2627
- inquiry: META_RUNTIME_STATUS_INTENT,
2628
- responded: 1,
2629
- failed: 0,
2630
- timedOut: 0,
2631
- pending: 0,
2632
- directStatusCheck: true
2672
+ const directStatusCheck = instance ? await this.requestRuntimeStatusViaRest(
2673
+ instance,
2674
+ serviceName,
2675
+ serviceInstanceId
2676
+ ) : {
2677
+ report: null,
2678
+ diagnostic: {
2679
+ attempted: false,
2680
+ outcome: "instance_missing"
2681
+ }
2682
+ };
2683
+ if (directStatusCheck.report) {
2684
+ if (!this.applyRuntimeStatusReport(directStatusCheck.report)) {
2685
+ throw this.createRuntimeStatusFallbackError(
2686
+ `No tracked instance for runtime fallback ${serviceName}/${serviceInstanceId}`,
2687
+ {
2688
+ target: {
2689
+ serviceName,
2690
+ serviceInstanceId
2691
+ },
2692
+ instance: this.summarizeInstanceForRuntimeStatusFallback(instance),
2693
+ directStatusCheck: directStatusCheck.diagnostic,
2694
+ inquiry: {
2695
+ meta: {},
2696
+ reportTargets: []
2697
+ }
2633
2698
  }
2634
- };
2699
+ );
2635
2700
  }
2701
+ this.lastHeartbeatAtByInstance.set(serviceInstanceId, Date.now());
2702
+ this.missedHeartbeatsByInstance.set(serviceInstanceId, 0);
2703
+ return {
2704
+ report: directStatusCheck.report,
2705
+ inquiryMeta: {
2706
+ inquiry: META_RUNTIME_STATUS_INTENT,
2707
+ responded: 1,
2708
+ failed: 0,
2709
+ timedOut: 0,
2710
+ pending: 0,
2711
+ directStatusCheck: true
2712
+ }
2713
+ };
2636
2714
  }
2637
2715
  const inquiryResult = await CadenzaService.inquire(
2638
2716
  META_RUNTIME_STATUS_INTENT,
@@ -2654,13 +2732,37 @@ var ServiceRegistry = class _ServiceRegistry {
2654
2732
  serviceInstanceId
2655
2733
  );
2656
2734
  if (!report) {
2657
- throw new Error(
2658
- `No runtime status report for ${serviceName}/${serviceInstanceId}`
2735
+ throw this.createRuntimeStatusFallbackError(
2736
+ `No runtime status report for ${serviceName}/${serviceInstanceId}`,
2737
+ {
2738
+ target: {
2739
+ serviceName,
2740
+ serviceInstanceId
2741
+ },
2742
+ instance: this.summarizeInstanceForRuntimeStatusFallback(instance),
2743
+ directStatusCheck: directStatusCheck.diagnostic,
2744
+ inquiry: {
2745
+ meta: inquiryResult.__inquiryMeta && typeof inquiryResult.__inquiryMeta === "object" ? inquiryResult.__inquiryMeta : {},
2746
+ reportTargets: this.summarizeRuntimeStatusInquiryReports(inquiryResult)
2747
+ }
2748
+ }
2659
2749
  );
2660
2750
  }
2661
2751
  if (!this.applyRuntimeStatusReport(report)) {
2662
- throw new Error(
2663
- `No tracked instance for runtime fallback ${serviceName}/${serviceInstanceId}`
2752
+ throw this.createRuntimeStatusFallbackError(
2753
+ `No tracked instance for runtime fallback ${serviceName}/${serviceInstanceId}`,
2754
+ {
2755
+ target: {
2756
+ serviceName,
2757
+ serviceInstanceId
2758
+ },
2759
+ instance: this.summarizeInstanceForRuntimeStatusFallback(instance),
2760
+ directStatusCheck: directStatusCheck.diagnostic,
2761
+ inquiry: {
2762
+ meta: inquiryResult.__inquiryMeta && typeof inquiryResult.__inquiryMeta === "object" ? inquiryResult.__inquiryMeta : {},
2763
+ reportTargets: this.summarizeRuntimeStatusInquiryReports(inquiryResult)
2764
+ }
2765
+ }
2664
2766
  );
2665
2767
  }
2666
2768
  this.lastHeartbeatAtByInstance.set(serviceInstanceId, Date.now());
@@ -2672,11 +2774,23 @@ var ServiceRegistry = class _ServiceRegistry {
2672
2774
  }
2673
2775
  async requestRuntimeStatusViaRest(instance, serviceName, serviceInstanceId) {
2674
2776
  if (typeof globalThis.fetch !== "function") {
2675
- return null;
2777
+ return {
2778
+ report: null,
2779
+ diagnostic: {
2780
+ attempted: false,
2781
+ outcome: "fetch_unavailable"
2782
+ }
2783
+ };
2676
2784
  }
2677
2785
  const transport = this.getRouteableTransport(instance, "rest");
2678
2786
  if (!transport) {
2679
- return null;
2787
+ return {
2788
+ report: null,
2789
+ diagnostic: {
2790
+ attempted: false,
2791
+ outcome: "no_rest_transport"
2792
+ }
2793
+ };
2680
2794
  }
2681
2795
  const controller = typeof AbortController === "function" ? new AbortController() : null;
2682
2796
  const timeoutId = controller ? setTimeout(() => controller.abort(), this.runtimeStatusFallbackTimeoutMs) : null;
@@ -2686,7 +2800,16 @@ var ServiceRegistry = class _ServiceRegistry {
2686
2800
  signal: controller?.signal
2687
2801
  });
2688
2802
  if ("ok" in response && response.ok === false) {
2689
- return null;
2803
+ return {
2804
+ report: null,
2805
+ diagnostic: {
2806
+ attempted: true,
2807
+ outcome: "http_error",
2808
+ transport: this.summarizeTransportForDebug(transport),
2809
+ responseStatus: typeof response.status === "number" ? response.status : void 0,
2810
+ responseStatusText: typeof response.statusText === "string" ? response.statusText : void 0
2811
+ }
2812
+ };
2690
2813
  }
2691
2814
  const payload = typeof response.json === "function" ? await response.json() : response;
2692
2815
  const report = this.normalizeRuntimeStatusReport({
@@ -2696,14 +2819,46 @@ var ServiceRegistry = class _ServiceRegistry {
2696
2819
  transportProtocols: payload?.transportProtocols ?? transport.protocols
2697
2820
  });
2698
2821
  if (!report) {
2699
- return null;
2822
+ return {
2823
+ report: null,
2824
+ diagnostic: {
2825
+ attempted: true,
2826
+ outcome: "invalid_report",
2827
+ transport: this.summarizeTransportForDebug(transport),
2828
+ payloadKeys: payload && typeof payload === "object" ? Object.keys(payload).sort() : []
2829
+ }
2830
+ };
2700
2831
  }
2701
2832
  if (report.serviceName !== serviceName || report.serviceInstanceId !== serviceInstanceId) {
2702
- return null;
2833
+ return {
2834
+ report: null,
2835
+ diagnostic: {
2836
+ attempted: true,
2837
+ outcome: "identity_mismatch",
2838
+ transport: this.summarizeTransportForDebug(transport),
2839
+ payloadServiceName: report.serviceName,
2840
+ payloadServiceInstanceId: report.serviceInstanceId
2841
+ }
2842
+ };
2703
2843
  }
2704
- return report;
2705
- } catch {
2706
- return null;
2844
+ return {
2845
+ report,
2846
+ diagnostic: {
2847
+ attempted: true,
2848
+ outcome: "matched",
2849
+ transport: this.summarizeTransportForDebug(transport)
2850
+ }
2851
+ };
2852
+ } catch (error) {
2853
+ return {
2854
+ report: null,
2855
+ diagnostic: {
2856
+ attempted: true,
2857
+ outcome: "fetch_error",
2858
+ transport: this.summarizeTransportForDebug(transport),
2859
+ error: error instanceof Error ? error.message : String(error)
2860
+ }
2861
+ };
2707
2862
  } finally {
2708
2863
  if (timeoutId) {
2709
2864
  clearTimeout(timeoutId);