-
Notifications
You must be signed in to change notification settings - Fork 400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Do not use static state variables in Extension class #389
base: master
Are you sure you want to change the base?
Do not use static state variables in Extension class #389
Conversation
ce9c34f
to
f016d03
Compare
@@ -75,7 +76,7 @@ public void checkRequiredPermission() { | |||
public HttpResponse doGetLastDuplicatePayload() { | |||
Jenkins.get().checkPermission(Jenkins.SYSTEM_READ); | |||
JSONObject data; | |||
var lastDuplicate = DuplicateEventsSubscriber.getLastDuplicate(); | |||
var lastDuplicate = ExtensionList.lookupSingleton(DuplicateEventsSubscriber.class).getLastDuplicate(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm using ExtensionList.lookupSingleton
in two places in this class.
I considered keeping a class-level subscriber field, but that seem to require extra code to manage the reference correctly.
- Since both this monitor class and the subscriber have
@Extension
, I think they can't store direct references to each other—perhaps because their initialization order isn't guaranteed? - We could store the reference during execution (
if (subscriber != null) { subscriber = ExtensionList.lookupSingleton(...); }
), but extensions are already looked up in more hot code path - ref code (executed for every event)
So I think this approach is fine - (ExtensionList.lookupSingleton
probably doesn't introduce any overhead)
return eventTracker.asMap().keySet().stream() | ||
.filter(key -> eventTracker.getIfPresent(key) != null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW I think this would be better written using a stream on entrySet
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
entrySet
because it is more performance optimal?
would be like,
return eventTracker.asMap().entrySet().stream()
.filter(entry -> entry.getValue() != null)
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
But since this is a helper method for tests only, and we only need the keys, ig probably keeping on keySet()
is easy read.. 🤔
(I now renamed the method to getPresentEventKeys
which makes more sense)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah it is just a bad pattern to iterate a map’s key set and then look up the value each time. Does not really matter of course.
Flakiness in the test was identified (possibly) due to the use of static stateful fields in the
@Extension
class. See this comment for details. Issue was likely parallel test execution mutating the state of static field.This PR addresses the issue following the comment here.
Note: This problem only affects tests and does not impact Jenkins functionality. Whether the data is stored in a static cache or within a field inside a singleton instance, it effectively centralizes event data in one place.
Testing done
Submitter checklist