From 53825a1dde1fd8a31a728b28c90f0f75b5d23881 Mon Sep 17 00:00:00 2001 From: Tomas Bjerre Date: Sat, 13 Apr 2024 18:35:31 +0200 Subject: [PATCH] feat: optimizing retrieval of jobs when using token to auth --- logging.properties | 4 +- .../gwt/jobfinder/GenericTriggerFinder.java | 21 +++++ .../plugins/gwt/jobfinder/JobFinder.java | 19 +---- .../gwt/jobfinder/JobFinderImpersonater.java | 84 ++++++++++++++++++- 4 files changed, 106 insertions(+), 22 deletions(-) create mode 100644 src/main/java/org/jenkinsci/plugins/gwt/jobfinder/GenericTriggerFinder.java diff --git a/logging.properties b/logging.properties index 334d00f4..50225804 100644 --- a/logging.properties +++ b/logging.properties @@ -1,6 +1,6 @@ # Logging handlers = java.util.logging.ConsoleHandler -org.jenkinsci.plugins.gwt.level = FINE +org.jenkinsci.plugins.gwt.level = FINEST # Console Logging -java.util.logging.ConsoleHandler.level = FINE +java.util.logging.ConsoleHandler.level = FINEST diff --git a/src/main/java/org/jenkinsci/plugins/gwt/jobfinder/GenericTriggerFinder.java b/src/main/java/org/jenkinsci/plugins/gwt/jobfinder/GenericTriggerFinder.java new file mode 100644 index 00000000..72357be0 --- /dev/null +++ b/src/main/java/org/jenkinsci/plugins/gwt/jobfinder/GenericTriggerFinder.java @@ -0,0 +1,21 @@ +package org.jenkinsci.plugins.gwt.jobfinder; + +import hudson.triggers.Trigger; +import hudson.triggers.TriggerDescriptor; +import java.util.Map; +import org.jenkinsci.plugins.gwt.GenericTrigger; + +public class GenericTriggerFinder { + public static GenericTrigger findGenericTrigger( + final Map> triggers) { + if (triggers == null) { + return null; + } + for (final Trigger candidate : triggers.values()) { + if (candidate instanceof GenericTrigger) { + return (GenericTrigger) candidate; + } + } + return null; + } +} diff --git a/src/main/java/org/jenkinsci/plugins/gwt/jobfinder/JobFinder.java b/src/main/java/org/jenkinsci/plugins/gwt/jobfinder/JobFinder.java index 823fc3c5..0fe177ee 100644 --- a/src/main/java/org/jenkinsci/plugins/gwt/jobfinder/JobFinder.java +++ b/src/main/java/org/jenkinsci/plugins/gwt/jobfinder/JobFinder.java @@ -7,11 +7,8 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; import hudson.model.Item; -import hudson.triggers.Trigger; -import hudson.triggers.TriggerDescriptor; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import jenkins.model.ParameterizedJobMixIn.ParameterizedJob; @@ -40,7 +37,8 @@ public static List findAllJobsWithTrigger(final String givenToken) { final List candidateProjects = jobFinderImpersonater.getAllParameterizedJobs(impersonate); for (final ParameterizedJob candidateJob : candidateProjects) { - final GenericTrigger genericTriggerOpt = findGenericTrigger(candidateJob.getTriggers()); + final GenericTrigger genericTriggerOpt = + GenericTriggerFinder.findGenericTrigger(candidateJob.getTriggers()); if (genericTriggerOpt != null) { final String configuredToken = determineTokenValue( @@ -116,17 +114,4 @@ private static boolean authenticationTokenMatchesGeneric( } return false; } - - private static GenericTrigger findGenericTrigger( - final Map> triggers) { - if (triggers == null) { - return null; - } - for (final Trigger candidate : triggers.values()) { - if (candidate instanceof GenericTrigger) { - return (GenericTrigger) candidate; - } - } - return null; - } } diff --git a/src/main/java/org/jenkinsci/plugins/gwt/jobfinder/JobFinderImpersonater.java b/src/main/java/org/jenkinsci/plugins/gwt/jobfinder/JobFinderImpersonater.java index 1cdfede0..c3077165 100644 --- a/src/main/java/org/jenkinsci/plugins/gwt/jobfinder/JobFinderImpersonater.java +++ b/src/main/java/org/jenkinsci/plugins/gwt/jobfinder/JobFinderImpersonater.java @@ -1,19 +1,47 @@ package org.jenkinsci.plugins.gwt.jobfinder; +import hudson.Extension; +import hudson.model.Item; +import hudson.model.listeners.ItemListener; import hudson.security.ACL; +import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.TreeSet; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; import java.util.logging.Logger; import jenkins.model.Jenkins; import jenkins.model.ParameterizedJobMixIn.ParameterizedJob; import org.acegisecurity.context.SecurityContext; import org.acegisecurity.context.SecurityContextHolder; -public class JobFinderImpersonater { +@Extension +public class JobFinderImpersonater extends ItemListener { private static Logger LOGGER = Logger.getLogger(JobFinderImpersonater.class.getName()); - - public JobFinderImpersonater() {} + private static final Map JOBS_WITH_GWT = new ConcurrentHashMap<>(); public List getAllParameterizedJobs(final boolean impersonate) { + if (LOGGER.isLoggable(Level.FINEST)) { + LOGGER.finest("There are " + this.JOBS_WITH_GWT.size() + " jobs in cache:"); + final TreeSet sortedSet = new TreeSet<>(this.JOBS_WITH_GWT.keySet()); + for (final String job : sortedSet) { + LOGGER.finest(" " + job); + } + } + if (impersonate) { + LOGGER.log(Level.FINE, "Using the cache"); + return new ArrayList<>(this.JOBS_WITH_GWT.values()); + } + LOGGER.log( + Level.FINE, + "Not using the cache because jobs are not retreieved with impersonation SYSTEM. " + + "SYSTEM is only impersonated when using a token." + + " If SYSTEM is not impersonated, only jobs available for the currently authenticated user is found."); + return doGetAllParameterizedJobs(impersonate); + } + + private static List doGetAllParameterizedJobs(final boolean impersonate) { SecurityContext orig = null; try { if (impersonate) { @@ -26,4 +54,54 @@ public List getAllParameterizedJobs(final boolean impersonate) } } } + + @Override + public void onLoaded() { + for (final ParameterizedJob job : doGetAllParameterizedJobs(true)) { + this.putJob(job); + } + LOGGER.info("Loaded " + this.JOBS_WITH_GWT.size() + " jobs in cache"); + } + + @Override + public void onUpdated(final Item job) { + this.putJob(job); + } + + @Override + public void onCreated(final Item job) { + this.putJob(job); + } + + @Override + public void onDeleted(final Item job) { + this.deleteJob(job); + } + + @Override + public void onCopied(final Item src, final Item job) { + this.putJob(job); + } + + @Override + public void onLocationChanged( + final Item item, final String oldFullName, final String newFullName) { + this.JOBS_WITH_GWT.remove(oldFullName); + this.putJob(item); + } + + private void putJob(final Item job) { + if (job instanceof ParameterizedJob) { + final ParameterizedJob parameterizedJob = (ParameterizedJob) job; + final boolean hasGenericTrigger = + GenericTriggerFinder.findGenericTrigger(parameterizedJob.getTriggers()) != null; + if (hasGenericTrigger) { + this.JOBS_WITH_GWT.put(parameterizedJob.getFullName(), parameterizedJob); + } + } + } + + private void deleteJob(final Item job) { + this.JOBS_WITH_GWT.remove(job.getFullName()); + } }