Class NodeExecutorTracker

java.lang.Object
hudson.slaves.ComputerListener
io.jenkins.plugins.smartexecutorloadbalancer.NodeExecutorTracker
All Implemented Interfaces:
ExtensionPoint, ExecutorListener

@Extension public class NodeExecutorTracker extends ComputerListener implements ExecutorListener
Listens to every executor-slot lifecycle event and records the outcome in NodeLabelStatsStore.

Task routing

For freestyle builds (AbstractProject), taskCompleted fires after the build result has been set. FreestyleBuildTracker handles those via RunListener. NodeExecutorTracker skips them to avoid double-counting and only cleans up maps.

For pipeline node() blocks the outcome is determined per executor slot by inspecting the BlockStartNode returned by ExecutorStepExecution.PlaceholderTask.getNode(). At taskCompleted(Executor, Queue.Task, long) we look up the corresponding BlockEndNode: if it carries an ErrorAction the script inside the block failed → FailureType.CODE_FAULT; no ErrorAction means the slot exited cleanly → FailureType.NONE. Infrastructure failures (channel crash, OOM, agent timeout) can surface via taskCompletedWithProblemsFailureType.NODE_FAULT, but for JNLP agents this callback never fires because executor threads run in the agent JVM and die with it. onTemporarilyOffline(Computer, OfflineCause) (a ComputerListener hook) fires on the controller the moment the agent channel closes; any executor still holding a task at that point is recorded as FailureType.NODE_FAULT directly. A guard set prevents double-recording if taskCompleted later fires for the same executor.

Parallel pipelines are handled correctly: each node() block has its own BlockStartNode, so a failing branch only marks the agent that ran that branch as CODE_FAULT; healthy parallel agents are unaffected.

Queue.FlyweightTask tasks (internal housekeeping) and OneOffExecutor tasks (workspace cleanup, etc.) are excluded: they are not real builds and should not influence node-health scoring.