Skip to content

Aggregate per-item error counts across all pipeline stages (#335) - #336

Merged
Chris-Wolfgang merged 1 commit into
vNext-plus-onefrom
feat/335-aggregate-errors
Jul 28, 2026
Merged

Aggregate per-item error counts across all pipeline stages (#335)#336
Chris-Wolfgang merged 1 commit into
vNext-plus-onefrom
feat/335-aggregate-errors

Conversation

@Chris-Wolfgang

Copy link
Copy Markdown
Owner

Closes #335. Stacked on #334 (#93) — base is feat/93-middleware.

Summary

Fixes the base-class asymmetry surfaced while reviewing the #93/#94 error interaction: the #84 error mechanism is on all three base classes, but EtlPipelineProgress.ErrorItemCount only reflected the extractor's errors. Root cause — CurrentErrorItemCount lived only on the concrete bases, and Through(ITransformAsync<…>) takes an interface that didn't expose it, so the pipeline structurally couldn't read a transformer's error count.

Changes

  • New IReportsItemErrorsint CurrentErrorItemCount { get; }, implemented by ExtractorBase, LoaderBase, TransformerBase (the property already existed — purely additive).
  • EtlRunState now holds a list of error-count readers and sums them in Snapshot().
  • Every error-reporting stage registers a reader as the factory chain runs: the extractor (From), each transformer (Through, via is IReportsItemErrors — so a bare ITransformAsync that opts in counts too), and the loader (sink).

EtlPipelineProgress.ErrorItemCount now reports the total items any stage's error policy discarded.

Behaviour change (pre-1.0)

ErrorItemCount was extractor-only; it now aggregates source + transformers + loader. 0.19.0 hasn't shipped, so no released consumer depends on the old meaning. Documented in the CHANGELOG.

Verification

  • 446 unit tests pass (5 new AggregateErrorsTests: sum across all three stages 2+4+1=7, delegate stage contributes 0, zero when nothing reports, plain-ITransformAsync overload, and the interface is implemented by all three bases).
  • Stryker 100.00 %, 0 survivors (full project).
  • Builds clean across all 11 TFMs; PublicAPI.Unshipped updated (RS0016 completeness + RS0017 correctness both validated).

Notes for release-prep

Targets the 0.20.0 line (vNext-plus-one). Version bump 0.19.0 → 0.20.0 + baseline → 0.19.0 deferred to 0.20.0 release-prep (gated on 0.19.0 publishing).

Fix the base-class asymmetry: CurrentErrorItemCount lived only on the concrete base
classes, so EtlPipelineProgress.ErrorItemCount could only surface the extractor's errors
(Through takes ITransformAsync, an interface that didn't expose it).

- Add IReportsItemErrors { int CurrentErrorItemCount { get; } }, implemented by
  ExtractorBase, LoaderBase, TransformerBase (property already existed — additive).
- EtlRunState now holds a list of error-count readers and sums them in Snapshot().
- Register a reader from every stage that reports errors: the extractor (From), each
  transformer (Through, via 'is IReportsItemErrors'), and the loader (sink). ErrorItemCount
  now reflects items ANY stage's error policy discarded. Pre-1.0 behaviour change.

- 5 AggregateErrorsTests (sum across all three stages, delegate stage contributes 0, zero
  when nothing reports, plain-ITransformAsync overload, interface implemented by all bases).
  446 unit tests pass; Stryker 100.00% (0 survivors).
- PublicAPI.Unshipped updated (RS0016 completeness + RS0017 correctness validated).
- CHANGELOG [Unreleased] Added + Changed entries.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 28, 2026 02:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants