ChemPal Documentation - v1.6.0
    Preparing search index...

    Function classifySupplierHealth

    • Classifies a supplier's connection and parsing health from its totals.

      A supplier the user has turned off reports disabled outright — its historical counters say nothing about current health, so grading them would be misleading.

      Otherwise each category is graded as a share of its attempts, at two tiers — "excessive" at EXCESSIVE_RATIO, critical at total failure — and the worst applicable status becomes the headline:

      • noSuccess — calls were made and none succeeded (critical connection).
      • connectionErrors — at least half of all calls failed.
      • parseFailure — every successful call failed to parse (critical parser).
      • parseErrors — at least half of successful calls failed to parse.

      Parse health is measured against successful calls, not products. Products would be a misleading denominator: uniqueProductCount only counts non-cached detail fetches, so a supplier serving cached results — or one that never fetches detail pages — reports zero products while parsing perfectly well.

      A supplier with no recorded activity is ok rather than flagged: absence of traffic isn't evidence of a problem.

      Parameters

      • totals: SupplierTotals

        The supplier's aggregated counters for the selected range.

      • disabled: boolean = false

        Whether the user has disabled this supplier in settings.

      Returns { status: SupplierHealthStatus; reasons: SupplierHealthStatus[] }

      The worst applicable status, plus every applicable reason for tooltips.

      classifySupplierHealth({ success: 114, failure: 14, products: 0, parseErrors: 10 });
      // => { status: "ok", reasons: [] } // 11% failures, 9% parse errors
      classifySupplierHealth({ success: 0, failure: 4, products: 0, parseErrors: 0 });
      // => { status: "noSuccess", reasons: ["noSuccess"] }
      classifySupplierHealth({ success: 10, failure: 0, products: 0, parseErrors: 10 });
      // => { status: "parseFailure", reasons: ["parseFailure"] }
      export function classifySupplierHealth(
      totals: SupplierTotals,
      disabled: boolean = false,
      ): {
      status: SupplierHealthStatus;
      reasons: SupplierHealthStatus[];
      } {
      if (disabled) {
      return { status: 'disabled', reasons: [] };
      }

      const { success, failure, parseErrors } = totals;
      const reasons: SupplierHealthStatus[] = [];

      const calls = success + failure;
      if (calls > 0) {
      if (success === 0) {
      reasons.push('noSuccess');
      } else if (failure / calls >= EXCESSIVE_RATIO) {
      reasons.push('connectionErrors');
      }
      }

      // Only successful calls return a body to parse, so they're the denominator.
      // When success is 0 the connection status already tells the story.
      if (success > 0 && parseErrors > 0) {
      if (parseErrors >= success) {
      reasons.push('parseFailure');
      } else if (parseErrors / success >= EXCESSIVE_RATIO) {
      reasons.push('parseErrors');
      }
      }

      const status = SEVERITY_ORDER.find((candidate) => reasons.includes(candidate)) ?? 'ok';
      return { status, reasons };
      }