Skip to content

refactor: weekly code-quality pass — 5 fixes (2026-06-29)#312

Merged
baoduy merged 1 commit into
devfrom
chore/code-quality-2026-06-29
Jun 28, 2026
Merged

refactor: weekly code-quality pass — 5 fixes (2026-06-29)#312
baoduy merged 1 commit into
devfrom
chore/code-quality-2026-06-29

Conversation

@baoduy

@baoduy baoduy commented Jun 28, 2026

Copy link
Copy Markdown
Owner

Weekly code-quality pass (2026-06-29)

Five targeted improvements found by reviewing the library source. Each is low-risk and behaviour-preserving on the success path. Categories: correctness/robustness, cancellation propagation, perf, and magic-number cleanup.

1. Harden fire-and-forget audit publishing — EfCoreAuditHook

The background Task.Run that runs audit publishers only caught DbUpdateException. Any other publisher failure escaped as an unobserved task exception, which can surface on the finalizer thread and tear down the process. Now catches Exception and logs it, explicitly discards the fire-and-forget task (_ =), and renames the void PublishLogsAsyncPublishLogs (it returns no awaitable).

2. Propagate CancellationToken through paging APIs

SpecRepoExtensions.ToPagedListAsync (both overloads), ModelSpecRepoExtensions.ToPagedListAsync, and RepoExtensions.SpecsToPageListAsync took no token, so a paged query could not be cancelled mid-flight. Added an optional CancellationToken and flowed it into X.PagedList.EF.ToPagedListAsync.

3. Name the default page size — PageAsyncEnumeratorExtensions

ToPageEnumerable(..., int pageSize = 100)DefaultPageSize constant.

4. Name the default SAS lifetime — AzureStorageBlobService

Hardcoded TimeSpan.FromDays(1) for the default SAS expiry → DefaultSasLifetime field, with a clearer comment.

5. Drop gratuitous Task.RunTokenResolver.ResolveAsync

Resolve is synchronous, CPU-bound reflection. Wrapping it in Task.Run inside a library wastes a thread-pool thread and adds a context switch for no benefit. Returns Task.FromResult(...) and lets the caller decide whether to offload. (ITokenExtractor.ExtractAsync was intentionally left as-is — it is fanned out via Task.WhenAll, where the offload provides real parallelism.)

Verification

  • dotnet build DKNet.FW.sln -c Debug0 warnings, 0 errors (TreatWarningsAsErrors=true).
  • Tests passing: Transform (44/44), Fw.Extensions (149/149), Repos paging (2/2), Specifications paging (31/31).
  • MsSql TestContainers integration tests are skipped/failing only because the SQL Server amd64 image segfaults under QEMU on the ARM host (environment limitation). One AuditLogs fire-and-forget timing test is flaky under parallel execution on dev too (verified by reverting the hook) — unrelated to this change.

🤖 Generated with Claude Code

…on, perf)

1. AuditLogs: harden fire-and-forget publishing in EfCoreAuditHook. The
   background Task.Run only caught DbUpdateException, so any other publisher
   failure became an unobserved task exception (can tear down the process on
   finalization). Broaden to catch Exception + log, mark the task discarded
   with `_ =`, and rename the void PublishLogsAsync -> PublishLogs (it is not
   awaitable).

2. Specifications/Repos: propagate CancellationToken through the paging APIs.
   SpecRepoExtensions.ToPagedListAsync (both overloads),
   ModelSpecRepoExtensions.ToPagedListAsync and RepoExtensions.SpecsToPageListAsync
   accepted no token and could not be cancelled mid-query. Add an optional
   CancellationToken and flow it into X.PagedList.EF.ToPagedListAsync.

3. Specifications: replace the magic default page size in
   PageAsyncEnumeratorExtensions.ToPageEnumerable (100) with a named
   DefaultPageSize constant.

4. AzureStorage: replace the hardcoded TimeSpan.FromDays(1) SAS expiry magic
   value with a named DefaultSasLifetime field and clarify the comment.

5. Transformation: TokenResolver.ResolveAsync wrapped synchronous, CPU-bound
   reflection work in Task.Run, needlessly offloading to the thread pool inside
   a library. Return Task.FromResult(...) instead.

Solution builds clean (0 warnings, TreatWarningsAsErrors). Transform (44),
Fw.Extensions (149), Repos paging (2) and Specifications paging (31) tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
@github-actions

Copy link
Copy Markdown

📊 Code Coverage Report

| Metric | Coverage |
|--------|----------|
| **Line Coverage** | 87.8% |
| **Branch Coverage** | 80.6% |
| **Method Coverage** | 86% |

**Lines:** 3267/undefined covered
**Branches:** 1211/undefined covered

📈 [View Full Coverage Report](https://github.com/baoduy/DKNet/actions/runs/28331730333)

@codecov

codecov Bot commented Jun 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 84.26%. Comparing base (b06bb04) to head (c06d416).

Additional details and impacted files
@@            Coverage Diff             @@
##              dev     #312      +/-   ##
==========================================
+ Coverage   84.15%   84.26%   +0.10%     
==========================================
  Files         159      159              
  Lines        3712     3718       +6     
  Branches      574      574              
==========================================
+ Hits         3124     3133       +9     
+ Misses        412      409       -3     
  Partials      176      176              
Flag Coverage Δ
unittests 84.26% <100.00%> (+0.10%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@baoduy baoduy merged commit 10fe8cd into dev Jun 28, 2026
6 checks passed
@baoduy baoduy deleted the chore/code-quality-2026-06-29 branch June 28, 2026 22:55
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.

1 participant