Skip to content

fix: two high-severity host crashes (#232 AuditMiddleware DbContext race, #223 RateLimiting missing table) - #241

Closed
antosubash wants to merge 2 commits into
mainfrom
claude/github-issues-ap2fC
Closed

antosubash wants to merge 2 commits into
mainfrom
claude/github-issues-ap2fC

Conversation

@antosubash

Copy link
Copy Markdown
Owner

Summary

Fixes two independent, high-severity runtime crashes.

#232 — AuditMiddleware races SettingsDbContext → intermittent 500s

AuditMiddleware ran on every request and fanned out five ISettingsContracts.GetSettingAsync(...) calls via Task.WhenAll. ISettingsContracts is scoped over a single SettingsDbContext, and on a cold FusionCache entry each call queries it — so the concurrent queries raced the context (A second operation was started on this context instance...), surfacing as intermittent HTTP 500s on the first hit after startup (reliably reproduced under concurrent browser/asset requests).

Fix: await the five lookups sequentially instead. The composite FusionCache entry still means this only runs on a cache miss (~once/60s), so there's no meaningful latency change.

#223 — RateLimitRuleCache crashes the host when RateLimiting_Rules is missing

RateLimitRuleCache is an IHostedService that queries RateLimiting_Rules in StartAsync. If the table doesn't exist — e.g. EnsureCreated() ran on an existing dev DB before RateLimiting was added, or migrations weren't applied — the unhandled provider exception crashed the entire host before it started listening.

Fix: catch DbException (provider-agnostic) in RefreshAsync, log a warning, and keep the current (empty at startup) snapshot so the host starts and degrades gracefully with no DB-defined rules.

Tests

  • AuditLogs: new regression test asserts the middleware never invokes the scoped settings service concurrently (would fail under the old Task.WhenAll). 10/10 pass.
  • RateLimiting: new regression test drives RefreshAsync against a context whose table was never created and asserts no throw. 8/8 pass.

Notes

Both fixes are minimal and independent — reviewable per-commit:

  • fix(auditlogs): load audit settings sequentially to avoid DbContext race (#232)
  • fix(ratelimiting): tolerate missing RateLimiting_Rules table on refresh (#223)

Closes #232
Closes #223


Generated by Claude Code

claude added 2 commits June 4, 2026 11:41
…ace (#232)

AuditMiddleware fanned out five GetSettingAsync calls via Task.WhenAll on
every request. ISettingsContracts is scoped over a single SettingsDbContext,
so on a cold FusionCache entry the concurrent queries raced the context
("A second operation was started on this context instance"), which the global
exception handler turned into intermittent HTTP 500s on the first hit after
startup.

Await the five lookups sequentially instead. Adds a regression test that fails
if the middleware ever invokes the scoped settings service concurrently.
…sh (#223)

RateLimitRuleCache is an IHostedService that queries RateLimiting_Rules in
StartAsync. If the table doesn't exist — e.g. EnsureCreated() ran on an
existing dev database before RateLimiting was added, or migrations weren't
applied — the unhandled provider exception crashed the entire host before it
could start listening.

Catch DbException in RefreshAsync, log a warning, and keep the current
(empty at startup) snapshot so the host starts and degrades gracefully with
no DB-defined rules. Adds a regression test covering the missing-table path.
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying simplemodule-website with  Cloudflare Pages  Cloudflare Pages

Latest commit: 8f47048
Status: ✅  Deploy successful!
Preview URL: https://a2258a79.simplemodule-website.pages.dev
Branch Preview URL: https://claude-github-issues-ap2fc.simplemodule-website.pages.dev

View logs

@antosubash
antosubash marked this pull request as ready for review June 4, 2026 19:53
@antosubash antosubash closed this Jun 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants