fix: harden stat flush locking and request validation#18
Merged
Conversation
- StatServerResource: validate from/to (and required fields) before deriving granularity so malformed /stats/view and /stats/compare requests return 400 instead of a 500 NPE - flushStats: null-check concurrently-removed buckets and skip gracefully - periodic flush: hold the per-bucket lock across flush + cache replacement to close a lost-update window across merge - on-demand flushStats(statClass, entityId): use the same statLockObj -> dateStats lock ordering as the periodic flush (consistent locking, no deadlock) Refs #17. Persistence-context/transaction item (#1) deferred for a test-backed change.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to #16, addressing 4 of the 5 hardening items tracked in #17. Compiles cleanly (
./mvnw clean compile); no public REST contract change.Changes
Request validation ordering (
StatServerResource)/stats/viewand/stats/comparenow validatefrom/to(and the other required fields) before callingcomputeGranularity, which dereferences both. Malformed requests now return400 Bad Requestinstead of a500(NPE).Defensive handling of concurrently-removed buckets (
StatBuilderService)Both flush methods now null-check the bucket fetched from the cache (it can be removed by a concurrent flush) and skip gracefully, instead of NPE-ing into a broad catch-all.
Stable locking around the periodic flush (
StatBuilderService)In the non-evict branch, the per-bucket lock is now held across the flush and the cache replacement (
put). This closes the window where a concurrent increment could be applied to the pre-merge instance and then discarded when the merged instance overwrote it (lost update).Consistent locking for on-demand flush (
StatBuilderService)flushStats(statClass, entityId)previously ran the flush under thedateStatsmonitor only. It now uses the samestatLockObj → dateStatslock ordering as the periodic flush, so the two paths are mutually exclusive and consistent. Verified no code path acquiresdateStatsbefore a stat lock, so the ordering introduces no deadlock.Not included
@Transactionalis effective on the internally-invoked flush method depends on runtime behavior that needs a DB-backed test; changing commit semantics here without that is risky. Tracked in Follow-up: thread-safety and robustness hardening in stat aggregation #17.Test plan
./mvnw clean compilepasses.getStatholdsdateStatsbut never acquires a stat lock inside it; flush now consistently takesstatLockObjthendateStats.Refs #17