Repository navigation
fix: address code-review findings (batch validation, stale-snapshot guard, rate limiter) - #15
Merged
Merged
Conversation
…uard, rate limiter) - TossMarketDataClient.fetchPrices: filter-and-warn invalid symbols instead of throwing for the whole batch; still rejects >200 valid symbols. - PriceSpikeRule / PriceVolumeSurgeRule: exclude snapshots older than a configurable max-age (detection.price-spike.max-age) from the recent-price average so prior-session leftovers cannot trigger false spikes at open. - ApiRateLimitFilter: optional trusted X-Forwarded-For support via marketguard.security.trusted-proxies; replace globally synchronized LRU map with per-key locked ConcurrentHashMap and purge stale windows before evicting active clients. - Tests added/updated for each fix. Co-authored-by: ox-alpha <noreply@nousresearch.com>
mytrashcan
commented
Aug 24, 2026
mytrashcan
left a comment
Owner
Author
There was a problem hiding this comment.
Review
Verified the diff in an isolated clone; CI fully green (verify, CodeQL, Analyze x2), merge state CLEAN.
Verified OK
- fetchPrices: invalid symbols filtered with warn log instead of killing the batch; >200 valid symbols still rejected; empty-after-filter short-circuits without an HTTP call. Matches the ETN resilience concern.
- PriceSpikeRule/PriceVolumeSurgeRule: maxAge staleness guard (config
detection.price-spike.max-age, default 30m) filters stale snapshots out of the recent-price average; all-stale history yields no detection. Constructor validation added. - ApiRateLimitFilter: optional trusted-proxy XFF resolution (hop-count from right, safe socket fallback prevents spoofing), per-key locked ConcurrentHashMap replacing the global synchronized LRU, overflow eviction purges stale windows before touching active ones.
- Tests added/updated across all three areas; -Werror + coverage gates satisfied.
Nit / Optional
boolean[] allowedas a compute() out-param works but a small holder record would read cleaner — author's discretion.
No blocking or should-fix issues found.
Reviewed by Hermes Agent
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
Fixes the three SHOULD-FIX findings from the code review:
TossMarketDataClient.fetchPricesno longer fails an entire batch on one bad symbol — invalid symbols are now filtered out with a warning log instead of throwingIllegalArgumentExceptionfor all 200 symbols. The upstream 200-symbol limit is still enforced against the valid remainder, and an all-invalid input short-circuits with no HTTP call.Stale-snapshot guard for recent-price averages —
PriceSpikeRule(and the price leg ofPriceVolumeSurgeRule) now excludes snapshots older than a configurablemax-age(detection.price-spike.max-age, default30m) from the "recent average". Prior-session leftovers can no longer produce false spike detections at market open; if every snapshot is stale, the rule stays silent.ApiRateLimitFilterhardeningmarketguard.security.trusted-proxiesproperty resolves the client from theX-Forwarded-Forchain, skipping the configured number of trusted hops (falls back to the socket address when the header is missing/short or when 0 proxies are trusted, so spoofing cannot bypass the limit).synchronizedLRU map with a per-key-lockedConcurrentHashMap, removing the global choke point on every/api/request.Tests
TossMarketDataClientCharacterizationTest; staleness tests inPriceSpikeRuleTestandPriceVolumeSurgeRuleTest; XFF resolution, spoof-resistance, and short-chain fallback inApiRateLimitFilterTest../gradlew buildpasses (all tests green,-Werror, JaCoCo 65% coverage gate).