Release v0.19.0 — overflow-safe progress counters - #337
Merged
Conversation
ExtractedItemCount / LoadedItemCount / ErrorItemCount are now long, so a long-running pipeline can report more than int.MaxValue (~2.1B) records without overflow. Changes the record's getters, positional ctor, and Deconstruct. - EtlRunState tracking fields widened to long; internal usages widen implicitly. - PublicAPI.Shipped updated; CompatibilitySuppressions.xml regenerated vs the new 0.18.0 baseline (55 CP0002 waivers for the int->long members) + justification. - Version 0.18.0 -> 0.19.0, baseline 0.17.0 -> 0.18.0. AssemblyVersion stays 1.0.0.0. - Added an overflow-safety test (counters hold > int.MaxValue). Breaking, pre-1.0. Full solution builds clean; 399 tests pass; pack passes Package Validation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Widen EtlPipelineProgress counters int -> long (#285)
#328) The residual Stryker survivors were all in the timer machinery — SystemProgressTimer (Start/StopTimer/Dispose guards) and the base CreateProgressTimer's timer.Start — and were only reachable by real-timer *timing* tests (flaky; System.Threading.Timer is post-dispose-safe so the guards read as equivalent). Introduce an internal ITimerCore seam: - SystemProgressTimer drives an ITimerCore (production = a thin System.Threading.Timer wrapper); an internal test ctor injects a fake core. - The 3 base classes gain an internal TimerCoreFactory so CreateProgressTimer builds its timer over an injectable core. TimerSeamTests use a FakeTimerCore that RECORDS Change/Dispose calls, making the Start/StopTimer/Dispose contract and each base's CreateProgressTimer.Start deterministically observable — no wall-clock ticks. All internal (no public API change). Mutation score 97.23% -> 100.00% (0 survivors); 409 tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Kill the 10 timer mutation survivors via a deterministic seam (#328)
# Conflicts: # src/Wolfgang.Etl.Abstractions/Wolfgang.Etl.Abstractions.csproj
- PackageValidationBaselineVersion 0.18.0 -> 0.18.1 (validate against the now-published 0.18.1); CompatibilitySuppressions still cover the int->long break vs 0.18.1 (pack green). - Promote CHANGELOG [Unreleased] -> [0.19.0] (2026-07-28); baseline note updated to 0.18.1. - Promote the Report timing ctor PublicAPI.Unshipped -> Shipped (ordinal); reset Unshipped. No code changes. 413 tests pass; pack + Package Validation green vs 0.18.1. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
BenchmarkDotNet
Details
| Benchmark suite | Current: b89a625 | Previous: 3a14ba9 | Ratio |
|---|---|---|---|
Wolfgang.Etl.Abstractions.Benchmarks.ExtractorBenchmarks.Extract_NoProgress(RecordCount: 1000) |
32153.659149169922 ns (± 271.3716530526001) |
31930.534067789715 ns (± 658.2371578009119) |
1.01 |
Wolfgang.Etl.Abstractions.Benchmarks.ExtractorBenchmarks.Extract_WithProgress(RecordCount: 1000) |
33935.63491821289 ns (± 120.3086629043112) |
34010.91799926758 ns (± 129.0833785595842) |
1.00 |
Wolfgang.Etl.Abstractions.Benchmarks.ExtractorBenchmarks.Extract_NoProgress(RecordCount: 100000) |
3202251.9049479165 ns (± 9609.219461803606) |
3106942.7135416665 ns (± 3078.2601995964997) |
1.03 |
Wolfgang.Etl.Abstractions.Benchmarks.ExtractorBenchmarks.Extract_WithProgress(RecordCount: 100000) |
3420486.3059895835 ns (± 19797.47197654614) |
3369861.2369791665 ns (± 3214.804757548345) |
1.02 |
Wolfgang.Etl.Abstractions.Benchmarks.PipelineBenchmarks.FluentPipeline(RecordCount: 1000) |
29940.04736836751 ns (± 123.36518324624471) |
29861.78623453776 ns (± 94.08997512637652) |
1.00 |
Wolfgang.Etl.Abstractions.Benchmarks.PipelineBenchmarks.ManualComposition(RecordCount: 1000) |
29013.722813924152 ns (± 41.61275689471991) |
29908.161814371746 ns (± 70.64600581703343) |
0.97 |
Wolfgang.Etl.Abstractions.Benchmarks.PipelineBenchmarks.BaseClassComposition(RecordCount: 1000) |
67647.85827636719 ns (± 225.2945243238395) |
68483.69946289062 ns (± 285.6650714675182) |
0.99 |
Wolfgang.Etl.Abstractions.Benchmarks.PipelineBenchmarks.FluentPipeline(RecordCount: 100000) |
2824819.7578125 ns (± 1034.5833105776833) |
2854886.4140625 ns (± 1462.1467840974312) |
0.99 |
Wolfgang.Etl.Abstractions.Benchmarks.PipelineBenchmarks.ManualComposition(RecordCount: 100000) |
2914988.14453125 ns (± 2706.130020031926) |
2870112.7330729165 ns (± 326.26898943322766) |
1.02 |
Wolfgang.Etl.Abstractions.Benchmarks.PipelineBenchmarks.BaseClassComposition(RecordCount: 100000) |
6693342.674479167 ns (± 37616.747084649534) |
6728828.515625 ns (± 4243.902731655375) |
0.99 |
This comment was automatically generated by workflow using github-action-benchmark.
…#338) Add an internal ITimeSource seam (StartedAt/Elapsed and the throughput metrics derived from them) so timing can be driven from a fake clock in tests, unblocking ETL-Test-Kit#262. - Internal ITimeSource + SystemTimeSource (default = DateTimeOffset.UtcNow + Stopwatch, net462-safe; NOT TimeProvider which is net8+). - ExtractorBase/LoaderBase/TransformerBase read StartedAt/Elapsed through an internal TimeSource field (mirrors the internal TimerCoreFactory seam); EtlRunState reads elapsed through an injected ITimeSource (internal ctor). Default behaviour identical (real clock). - InternalsVisibleTo("Wolfgang.Etl.TestKit") so Test-Kit doubles can inject a fake. NO public API change (all internal) — pack + Package Validation green vs 0.18.1. 419 tests (6 new ClockSeamTests); Stryker 100.00% (0 survivors); all 11 TFMs clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Injectable internal time source for deterministic Report timing (#338)
…elease day) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Jul 29, 2026
This was referenced Aug 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release: Wolfgang.Etl.Abstractions 0.19.0 — overflow-safe progress counters
Minor release. Bundles the 0.19.0 line from
vNext→main.What's in it
EtlPipelineProgresscounters (ExtractedItemCount/LoadedItemCount/ErrorItemCount) widenedint→long— overflow-safe pastint.MaxValue. Waived viaCompatibilitySuppressions.xmlagainst the 0.18.1 baseline.AssemblyVersionstays1.0.0.0. Pre-1.0.ITimerCoreseam that killed the 10 timer mutation survivors (100% mutation score). No public API change.Reporttiming ctor (merge-down already invNext).Release-prep done in this PR (commit 853ee46)
PackageValidationBaselineVersion0.18.0 → 0.18.1; pack + Package Validation green against the published 0.18.1.[Unreleased]→[0.19.0] - 2026-07-28.Reporttiming ctor promotedPublicAPI.Unshipped→Shipped(ordinal); Unshipped reset.Merging this PR is safe anytime —
release.yamlfires only onrelease:published, not on push tomain. But do not create thev0.19.0tag/release until after2026-07-29T00:00Z(≥ 8:00 PM EDT) so it lands on a NuGet UTC date (2026-07-29) distinct from 0.18.1's (2026-07-28). See the scheduled reminder.Tag
v0.19.0(bare), release title e.g.v0.19.0 — overflow-safe progress counters.No protected files in the diff → no admin bypass needed. The 0.20.0 stack (#333/#334/#336 on
vNext-plus-one) is separate and not part of this release.