From 64667af499e878f67b09e60bdf6ed0c2a549d545 Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Wed, 28 Aug 2024 09:54:25 +0200 Subject: [PATCH 1/5] Implement ComputerListener#onIdle Introduces a new computer listener fired whenever a Computer becomes idle. --- core/src/main/java/hudson/model/Computer.java | 2 ++ core/src/main/java/hudson/slaves/ComputerListener.java | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/core/src/main/java/hudson/model/Computer.java b/core/src/main/java/hudson/model/Computer.java index 14a311381a37..903751b90c13 100644 --- a/core/src/main/java/hudson/model/Computer.java +++ b/core/src/main/java/hudson/model/Computer.java @@ -1102,6 +1102,8 @@ protected void removeExecutor(final Executor e) { if (ciBase != null) { // TODO confirm safe to assume non-null and use getInstance() ciBase.removeComputer(Computer.this); } + } else if (isIdle()) { + Listeners.notify(ComputerListener.class, false, l -> l.onIdle(this)); } } }; diff --git a/core/src/main/java/hudson/slaves/ComputerListener.java b/core/src/main/java/hudson/slaves/ComputerListener.java index bd794c456c50..f5d220c1104e 100644 --- a/core/src/main/java/hudson/slaves/ComputerListener.java +++ b/core/src/main/java/hudson/slaves/ComputerListener.java @@ -211,6 +211,13 @@ public void onTemporarilyOffline(Computer c, OfflineCause cause) {} */ public void onConfigurationChange() {} + /** + * Indicates that the computer has become idle. + * + * @since TODO + */ + public void onIdle(Computer c) {} + /** * Registers this {@link ComputerListener} so that it will start receiving events. * From 9823b8ed7e3d6d5d5602860956a8fd10dad3c939 Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Wed, 28 Aug 2024 15:40:43 +0200 Subject: [PATCH 2/5] Execute ComputerListener#onIdle in another thread. --- core/src/main/java/hudson/model/Computer.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/hudson/model/Computer.java b/core/src/main/java/hudson/model/Computer.java index 903751b90c13..3cb7618ed3a9 100644 --- a/core/src/main/java/hudson/model/Computer.java +++ b/core/src/main/java/hudson/model/Computer.java @@ -100,6 +100,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger; @@ -114,6 +115,7 @@ import jenkins.util.ErrorLoggingExecutorService; import jenkins.util.Listeners; import jenkins.util.SystemProperties; +import jenkins.util.Timer; import jenkins.widgets.HasWidgets; import net.jcip.annotations.GuardedBy; import org.jenkins.ui.icon.Icon; @@ -1103,7 +1105,7 @@ protected void removeExecutor(final Executor e) { ciBase.removeComputer(Computer.this); } } else if (isIdle()) { - Listeners.notify(ComputerListener.class, false, l -> l.onIdle(this)); + threadPoolForRemoting.submit(() -> Listeners.notify(ComputerListener.class, false, l -> l.onIdle(this))); } } }; From 75242cf03010509e968f9de1a00ca6bb19d8b5fa Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Wed, 28 Aug 2024 15:47:51 +0200 Subject: [PATCH 3/5] Call listener synchronously, but outside synchronized --- core/src/main/java/hudson/model/Computer.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/hudson/model/Computer.java b/core/src/main/java/hudson/model/Computer.java index 3cb7618ed3a9..9400a70d3f53 100644 --- a/core/src/main/java/hudson/model/Computer.java +++ b/core/src/main/java/hudson/model/Computer.java @@ -1095,6 +1095,7 @@ public final long getDemandStartMilliseconds() { */ protected void removeExecutor(final Executor e) { final Runnable task = () -> { + var idle = false; synchronized (Computer.this) { executors.remove(e); oneOffExecutors.remove(e); @@ -1104,10 +1105,13 @@ protected void removeExecutor(final Executor e) { if (ciBase != null) { // TODO confirm safe to assume non-null and use getInstance() ciBase.removeComputer(Computer.this); } - } else if (isIdle()) { - threadPoolForRemoting.submit(() -> Listeners.notify(ComputerListener.class, false, l -> l.onIdle(this))); + } else { + idle = isIdle(); } } + if (idle) { + Listeners.notify(ComputerListener.class, false, l -> l.onIdle(this)); + } }; if (!Queue.tryWithLock(task)) { // JENKINS-28840 if we couldn't get the lock push the operation to a separate thread to avoid deadlocks From ed93ad020ae2e092242a89c6b714dca67c472559 Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Wed, 28 Aug 2024 16:12:09 +0200 Subject: [PATCH 4/5] Revert "Call listener synchronously, but outside synchronized" This reverts commit 75242cf03010509e968f9de1a00ca6bb19d8b5fa. --- core/src/main/java/hudson/model/Computer.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/hudson/model/Computer.java b/core/src/main/java/hudson/model/Computer.java index 9400a70d3f53..3cb7618ed3a9 100644 --- a/core/src/main/java/hudson/model/Computer.java +++ b/core/src/main/java/hudson/model/Computer.java @@ -1095,7 +1095,6 @@ public final long getDemandStartMilliseconds() { */ protected void removeExecutor(final Executor e) { final Runnable task = () -> { - var idle = false; synchronized (Computer.this) { executors.remove(e); oneOffExecutors.remove(e); @@ -1105,13 +1104,10 @@ protected void removeExecutor(final Executor e) { if (ciBase != null) { // TODO confirm safe to assume non-null and use getInstance() ciBase.removeComputer(Computer.this); } - } else { - idle = isIdle(); + } else if (isIdle()) { + threadPoolForRemoting.submit(() -> Listeners.notify(ComputerListener.class, false, l -> l.onIdle(this))); } } - if (idle) { - Listeners.notify(ComputerListener.class, false, l -> l.onIdle(this)); - } }; if (!Queue.tryWithLock(task)) { // JENKINS-28840 if we couldn't get the lock push the operation to a separate thread to avoid deadlocks From 6b88bfcbd5a1011983073cc2d283776b9ab68e5f Mon Sep 17 00:00:00 2001 From: Vincent Latombe Date: Wed, 28 Aug 2024 16:22:14 +0200 Subject: [PATCH 5/5] Spotless --- core/src/main/java/hudson/model/Computer.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/src/main/java/hudson/model/Computer.java b/core/src/main/java/hudson/model/Computer.java index 3cb7618ed3a9..c66759f94ab9 100644 --- a/core/src/main/java/hudson/model/Computer.java +++ b/core/src/main/java/hudson/model/Computer.java @@ -100,7 +100,6 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger; @@ -115,7 +114,6 @@ import jenkins.util.ErrorLoggingExecutorService; import jenkins.util.Listeners; import jenkins.util.SystemProperties; -import jenkins.util.Timer; import jenkins.widgets.HasWidgets; import net.jcip.annotations.GuardedBy; import org.jenkins.ui.icon.Icon;