Current outcome
Make the test utility inject the failures its callers request, so error-path tests cannot pass vacuously or use silently quantized rates.
Replanned on 2026-09-06 against GoBatch master 63ef757 and ShitQuant's recorder, enrichment, paper/replay, and flow workloads. This is an implementation target, not a claim that the behavior already exists.
Required behavior
Verification and completion
Test zero, all-fail, 0.4 and 0.6, boundaries/invalid values and the documented deterministic sequence. Verify error-path fixtures fail when injection is disabled.
Follow the repository's formatting, race-test, vet/lint, package documentation, example and changelog requirements for the changed surface. Report the actual supported behavior and migration; do not treat a passing coverage percentage as proof of these outcomes.
Scope and relationships
Useful to reliable lifecycle/error tests; independent of Redis or broad API ergonomics. Preserve intended upstream item errors under the agreed contract.
Design history
The earlier report/prototype remains below for provenance; the requirements above supersede conflicting prescriptions. Existing discussion is preserved.
Original issue: processor.Error: zero value is a silent no-op (docs claim FailFraction defaults to 1.0), and quantization makes any fraction in (0.5,1.0) fail 100%
Two defects in processor/error.go (validated on master @ 58cee73; found in a deep review):
1. Zero value contradicts the documented default. The FailFraction doc says "1.0 means all items will have errors (default)" and the type doc says it "marks all incoming items with the given error" — but Process treats failFraction <= 0 as pass-through (error.go:39-42). So the obvious construction &processor.Error[int]{Err: myErr} errors nothing, and tests that use it to verify error handling pass vacuously. The package's own test betrays this: it sets FailFraction: 1.0, // Default - apply to all manually.
2. Integer quantization. failEvery := int(1.0 / failFraction) (error.go:51) truncates: 0.6 → failEvery=1 → 100% of items fail; 0.4 → 2 → exactly 50%. Only rates of the form 1/n are achievable, and the deterministic every-Nth pattern isn't "approximately half" as the doc implies.
Suggested fix: decide the semantics explicitly — either honor the documented all-fail default (requires distinguishing unset from 0.0, e.g. a constructor per #74's direction) or fix the docs to say zero = no failures; document or replace the 1/n quantization. This is a testing utility, so a breaking change is fine under the v0 policy.
Relations: surfaced while validating #74 (factories would not fix either defect); independent of PRs #65/#66.
Current outcome
Make the test utility inject the failures its callers request, so error-path tests cannot pass vacuously or use silently quantized rates.
Replanned on 2026-09-06 against GoBatch master
63ef757and ShitQuant's recorder, enrichment, paper/replay, and flow workloads. This is an implementation target, not a claim that the behavior already exists.Required behavior
Verification and completion
Test zero, all-fail, 0.4 and 0.6, boundaries/invalid values and the documented deterministic sequence. Verify error-path fixtures fail when injection is disabled.
Follow the repository's formatting, race-test, vet/lint, package documentation, example and changelog requirements for the changed surface. Report the actual supported behavior and migration; do not treat a passing coverage percentage as proof of these outcomes.
Scope and relationships
Useful to reliable lifecycle/error tests; independent of Redis or broad API ergonomics. Preserve intended upstream item errors under the agreed contract.
Design history
The earlier report/prototype remains below for provenance; the requirements above supersede conflicting prescriptions. Existing discussion is preserved.
Original issue: processor.Error: zero value is a silent no-op (docs claim FailFraction defaults to 1.0), and quantization makes any fraction in (0.5,1.0) fail 100%
Two defects in
processor/error.go(validated on master @ 58cee73; found in a deep review):1. Zero value contradicts the documented default. The
FailFractiondoc says "1.0 means all items will have errors (default)" and the type doc says it "marks all incoming items with the given error" — butProcesstreatsfailFraction <= 0as pass-through (error.go:39-42). So the obvious construction&processor.Error[int]{Err: myErr}errors nothing, and tests that use it to verify error handling pass vacuously. The package's own test betrays this: it setsFailFraction: 1.0, // Default - apply to allmanually.2. Integer quantization.
failEvery := int(1.0 / failFraction)(error.go:51) truncates: 0.6 → failEvery=1 → 100% of items fail; 0.4 → 2 → exactly 50%. Only rates of the form 1/n are achievable, and the deterministic every-Nth pattern isn't "approximately half" as the doc implies.Suggested fix: decide the semantics explicitly — either honor the documented all-fail default (requires distinguishing unset from 0.0, e.g. a constructor per #74's direction) or fix the docs to say zero = no failures; document or replace the 1/n quantization. This is a testing utility, so a breaking change is fine under the v0 policy.
Relations: surfaced while validating #74 (factories would not fix either defect); independent of PRs #65/#66.