← back to La Socrata Ingester
src/run-policy.js
32 lines
// Aggregate-run failure policy. Exceptions live on source metadata so they are
// explicit, reviewable, and automatically disappear from this policy when the
// metadata is removed. A direct source/group run remains strict.
export function classifyRunResults(results, sources, targetToken) {
const failures = results.filter((result) => result.error);
const aggregateAll = targetToken === 'all';
// An allowFailure exemption must be scoped to the SPECIFIC audited failure, not to the
// source name. Otherwise it silences EVERY future error on that source — including an
// ArcGIS layer-identity drift, which is exactly the class the identity guard exists to
// make loud (TK-10955: upstream re-indexed and 7 sources silently ingested the wrong
// layer for 6 days). `match` is an array of substrings; a failure is tolerated only if
// its error text contains one of them. Omitting `match` keeps the older, broader
// behaviour for back-compat.
const isAuditedFailure = (result) => {
const allow = sources[result.name]?.allowFailure;
if (allow?.scope !== 'aggregate-all-only') return false;
if (!Array.isArray(allow.match) || allow.match.length === 0) return true;
const text = String(result.error ?? '');
return allow.match.some((needle) => text.includes(needle));
};
const tolerated = aggregateAll ? failures.filter(isAuditedFailure) : [];
const toleratedNames = new Set(tolerated.map((result) => result.name));
const unexpected = failures.filter((result) => !toleratedNames.has(result.name));
return {
failures,
tolerated,
unexpected,
exitCode: unexpected.length ? 1 : 0,
};
}