Conversation
|
@ejsmith could you review this specific cache-counter behavior before we simplify With Foundatio 13.0.4, .NET 10 on macOS arm64, five isolated runs of 10,000
This reproduction uses only an in-memory cache, without application services or network access. The decompiled implementation reads and mutates the same existing Exact reproductionCreate a .NET 10 console project with using Foundatio.Caching;
using var cache = new InMemoryCacheClient();
const int incrementCount = 10000;
for (int run = 0; run < 5; run++)
{
string key = $"counter-{run}";
await cache.SetAsync(key, 0L);
await Parallel.ForEachAsync(Enumerable.Range(0, incrementCount),
new ParallelOptions { MaxDegreeOfParallelism = 16 },
async (attempt, cancellationToken) => await cache.IncrementAsync(key, 1));
long actual = (await cache.GetAsync<long>(key)).Value;
Console.WriteLine($"Run {run + 1}: expected {incrementCount}, actual {actual}");
if (actual != incrementCount)
Environment.ExitCode = 1;
}This PR remains draft because simply replacing the markers with the current in-memory counter implementation would lose concurrent failures. The dependency should provide the atomic counter behavior so authentication can stay simple. |
|
Reviewing Roughly 80% of the additions are tests, and security regression coverage is justified. The concern is the production scope and the custom throttling machinery.
For the concurrency concern, a local reproduction using the actual Basic-auth handler with delayed repository responses admitted 100 requests before completion. It evaluated 99 incorrect passwords, and the final correct guess authenticated even after new requests were blocked. Admission needs to account for password checks already underway; the existing tests establish eventual blocking after failures complete. The Foundatio counter bug is real and was also reproduced locally, so simply replacing the markers with today's counters would be incorrect. Fix and test that underlying primitive separately, then use a small limiter with explicit handling of in-flight verification. Atomic counters alone do not solve the admission race. There is necessary complexity around concurrency, successful requests, and recovery. However, requiring successful authentication to perform no cache writes or distributed locking makes the design harder. That optimization should have a measured need, and successful requests should not consume failure quota. I recommend narrowing this PR to the limiter, its two authentication callers, recovery wiring, and targeted regression tests. That should make the change substantially smaller and easier to establish as correct. |
3cd7d98 to
f3425cb
Compare
f3425cb to
d1d1c99
Compare
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: da2f75b130
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
|
|
||
| private Task RemoveFailuresAsync(IEnumerable<KeyValuePair<string, string>> failures) | ||
| => Task.WhenAll(failures.Select(failure => _cache.RemoveIfEqualAsync(failure.Key, failure.Value))); |
There was a problem hiding this comment.
Require atomic compare-and-delete for admission slots
When concurrent successful logins observed the same prior failure, both call this removal; if a third login reserves that slot between the provider's comparison and deletion, the stale remover can delete the third login's reservation. The checked-in Foundatio 13.0.4 stack still has unresolved conditional-operation concurrency (upstream #570), while the new tests exercise only InMemoryCacheClient, so the five-user/fifteen-IP bounds are not established for the deployed provider. Use a provider-level atomic compare-and-delete primitive (or an equivalent lock) before relying on these entries for login admission.
Useful? React with 👍 / 👎.
Coordinates password login admission across interactive and Basic callers while preserving token aliases and fixed quarter-hour windows. Five user cache entries and fifteen IP cache entries share a budget between pending checks and completed failures. Explicit user/IP helpers retain canonical key construction and a single captured expiration.
Cleanup attempts every reserved key, preserves the original request error/cancellation, and logs the actual caught exception using the normal repository pattern. No fabricated exceptions, copied stacks or aggregate logging remain. Unexpected Basic-password repository errors are logged once; request cancellation keeps its existing failure-result behavior without an error log. No cache-key or credential properties are added to these logs. Logger injection is mandatory; attempt disposal uses a release callback.
All 83 test methods across the four retained files use three-part names, alphabetical ordering and explicit Arrange/Act/Assert sections. Historical comparison confirms all 60 endpoint methods and original service scenarios remain, with inline cases/assertions preserved. Requested HTTP examples and Elasticsearch test-infrastructure additions remain removed. Main's Svelte root-route cutover is preserved; descendants are unchanged.
Validation on
da2f75b13098ba6eeba89de5bedf51ee420002f9: 53 focused auth/parser/handler cases passed locally with no restore, including synchronous and faulted-task cleanup failures. Mechanical style audit and independent Astra review passed. Build 8226 passed on this exact head: all four API shards (3,206 passed, three skipped), all six browser shards (116 passed, zero skipped/flaky/retries), client formatting/lint/check/build, 1,006 frontend unit tests, all three Linux runtime tests, and Docker build. Publish/deployment jobs were skipped. The new Basic logging predicate was source-reviewed; no direct branch-coverage claim is made.Current slot accounting is unchanged. Rolling failures, simpler counter accounting and increasing cooldowns remain separate policy proposals. Production readiness remains unconfirmed: Foundatio 13.0.4 conditional-operation concurrency still requires affected-provider validation/upstream resolution (#570). Raw provider exception contents follow existing repository logging behavior and are not automatically redacted by the options-only logging policy. Cache-key migration restarts admission windows at deployment. No production provider-fault/multi-instance race testing or deployment validation occurred; no deployment was performed.