[AZ-359] Refactor C07: collapse RegionService catch ladder via RegionFailureClassifier
ci/woodpecker/push/01-test Pipeline was successful
ci/woodpecker/push/02-build-push Pipeline was successful

Replace 9 nearly-identical catch blocks in
RegionService.ProcessRegionAsync with a single catch (Exception ex)
that delegates to RegionFailureClassifier.Classify, returning a
typed (category, errorMessage) pair. Preserves all original error
messages stored in region summary files; failure-path call into
HandleProcessingFailureAsync is unchanged.

Net source delta: -38 lines in RegionService, +71 lines in new
RegionFailureClassifier (pure static), +10 unit tests covering
each category, precedence, status-code propagation, null guard.

Tests: 68 unit (was 58) + 5 smoke + 3 stub-contract integration
tests pass.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-11 00:07:31 +03:00
parent 1d89cd9997
commit 5a28f67d33
8 changed files with 312 additions and 48 deletions
@@ -0,0 +1,60 @@
# Refactor: consolidate 9-way catch ladder in RegionService.ProcessRegionAsync
**Task**: AZ-359_refactor_consolidate_region_catch_ladder
**Name**: Single catch + classifier in region processing
**Description**: Replace the nine near-identical catch blocks with a single `try/catch (Exception ex)` that delegates to a `ClassifyRegionFailure` helper.
**Complexity**: 3 points
**Dependencies**: None
**Component**: Services.RegionProcessing
**Tracker**: AZ-359
**Epic**: AZ-350
## Problem
`SatelliteProvider.Services.RegionProcessing/RegionService.cs:148-197` contains nine catch blocks (TaskCanceledException × 3, OperationCanceledException × 2, RateLimitException, HttpRequestException, Exception × 1) that each build an `errorMessage` and call `HandleProcessingFailureAsync`. Adding a new failure category requires touching all nine.
## Outcome
- One catch block; one classification helper.
- Same observable failure-path behavior preserved for all current categories (timeout, rate-limit, cancellation, generic).
- 37 unit + 5 smoke tests stay green.
## Scope
### Included
- Extract `ClassifyRegionFailure(Exception ex, CancellationTokenSource timeoutCts, CancellationToken cancellationToken) : (FailureCategory, string message)`.
- Replace the catch ladder with a single `catch (Exception ex)` that calls the helper and then `HandleProcessingFailureAsync`.
- Unit-test the classifier directly (cheaper than driving the full processing path).
### Excluded
- Changing the failure categories themselves.
- Adding new categories (deferred to future feature work).
## Acceptance Criteria
**AC-1: Each known exception still classifies correctly**
Given each of the previously-handled exception types (TaskCanceledException after timeout, after user cancel, OperationCanceledException, RateLimitException, HttpRequestException, generic Exception)
When `ClassifyRegionFailure` is called with that exception + the appropriate token state
Then it returns the same human message and category that the old catch block produced.
**AC-2: HandleProcessingFailureAsync called once**
Given any failure
When the catch block runs
Then `HandleProcessingFailureAsync` is called exactly once.
**AC-3: Tests stay green**
Given the post-refactor build
When `scripts/run-tests.sh --smoke` runs
Then all 37 unit + 5 smoke scenarios pass; `RegionTests` (timeout + rate-limit coverage) is unchanged.
## Constraints
- Same observable behavior for all currently-tested failure categories.
## Risks & Mitigation
**Risk 1: subtle category drift**
- *Risk*: a refactor may change which token (timeout vs user) was the cancellation source.
- *Mitigation*: the classifier takes the `timeoutCts` explicitly so it can disambiguate.
Full change entry: `_docs/04_refactoring/03-code-quality-refactoring/list-of-changes.md` (C07).