Fix: cache Status.TimeLocation() to stop HTTP request storm in EventStableChecker#350
Open
royteeuwen wants to merge 1 commit into
Open
Fix: cache Status.TimeLocation() to stop HTTP request storm in EventStableChecker#350royteeuwen wants to merge 1 commit into
royteeuwen wants to merge 1 commit into
Conversation
…hecker EventStableChecker.Check() calls instance.Time() once per OSGi event to determine event age, which resolves the instance timezone via Status.TimeLocation() on every call. Since TimeLocation() previously issued an uncached HTTP GET to /system/console/status-System%20Properties.json, a single event_stable check with N events triggered N HTTP requests, and this repeats on every poll while aemc awaits instance stability - easily producing thousands of requests per minute against a single instance. The instance's user.timezone JVM system property cannot change while a single aemc process is running, so it's safe to resolve it once per Status instance using sync.Once. Status methods are switched from value to pointer receivers since a struct containing a sync.Once must not be copied by value. Status is always accessed via a *Status field on Instance already, so this is a non-behavioral change. As a side effect this also fixes a latent bug where a time.LoadLocation failure returned (nil, nil) instead of propagating the error, which could cause a nil-pointer panic downstream in time.Time.In(nil).
Contributor
|
Tbh I have never seen any problems related to it. What's your motivation to fix this? |
Contributor
Author
|
We are noticing 1000's of http requests going to the instance, just to get the timezone again and again, which doesnt change? Inefficient and it pollutes the logs, why wouldnt you want to fix it if this can easily be cached? Is there a reason not to do it? |
Contributor
|
Just asking 🙂 you are right. Caching might be sometimes problematic. When to cache and when to revalidate... Etc. I will probably merge but give me some time for tests. |
Contributor
Author
|
Super, let me know if you need any changes ;) |
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.
Fixes #349
Problem
EventStableChecker.Check()resolves the instance's timezone viainstance.Time()→Status.TimeLocation()once per OSGi event beingevaluated, and
TimeLocation()previously issued an uncached HTTP GET to/system/console/status-System%20Properties.jsonon every call. A singleevent_stablecheck with N events therefore issues N HTTP requests, andthis repeats on every poll while
aemcwaits for instance stability(
instance await,instance start,package deploy, etc.), which canadd up to thousands of requests per minute against a single instance.
Fix
sync.Once-based caching toStatus.TimeLocation(), so theunderlying HTTP request happens at most once per
Statusobject (i.e.once per CLI invocation, per instance) instead of once per OSGi event
per poll. This is safe because the instance's
user.timezoneJVMsystem property is fixed at instance startup and cannot change during
a single
aemcprocess run.Statusmethods (SystemProps,SlingProps,SlingSettings,parseProperties,TimeLocation,RunModes,AemVersion) from value receivers to pointer receivers. This isrequired because a struct containing a
sync.Oncemust never becopied by value (
go vetflags "passes lock by value");Statusisalways accessed via a
*Statusfield onInstancealready, so thisis a non-behavioral change.
time.LoadLocationfailed, the function returned(timeLocation, nil)— i.e. a
nillocation with anilerror — which could cause anil-pointer panic in
time.Time.In(nil)downstream. The fix properlypropagates the error so the existing caller fallback
(
instance.TimeLocation()returningtime.Now().Location()on error)actually kicks in.
Verification
go build ./...— clean.go vet ./pkg/...— clean (no more "passes lock by value" warnings).go test ./...— all existing tests pass.building both a baseline (pre-fix) and fixed binary and running
instance awaitwith each, diffing the AEM request log for hits tostatus-System%20Properties.jsonover the same ~30s / 4-poll-roundwindow:
(
checked (4/4), all checks passing), confirming no behavioralregression.
Notes for reviewers
No test coverage currently exists for
pkg/status.goorpkg/check.go.Happy to add a unit test for
Status.TimeLocation()(e.g. viahttptest.Server, asserting the endpoint is hit exactly once acrossmultiple calls) if that's wanted before merge — let me know.