@@ -71,6 +71,20 @@ public class LockStep extends Step implements Serializable {
7171 @ SuppressFBWarnings (value = "PA_PUBLIC_PRIMITIVE_ATTRIBUTE" , justification = "Preserve API compatibility." )
7272 public int priority = 0 ;
7373
74+ /**
75+ * Timeout in the specified {@link #timeoutUnit} for waiting to acquire the resource.
76+ * 0 means no timeout (wait indefinitely). When the timeout expires, the step fails
77+ * with an exception instead of waiting forever.
78+ */
79+ @ SuppressFBWarnings (value = "PA_PUBLIC_PRIMITIVE_ATTRIBUTE" , justification = "Preserve API compatibility." )
80+ public long timeoutForAllocateResource = 0 ;
81+
82+ /**
83+ * Time unit for {@link #timeoutForAllocateResource}. Defaults to MINUTES.
84+ */
85+ @ SuppressFBWarnings (value = "PA_PUBLIC_PRIMITIVE_ATTRIBUTE" , justification = "Preserve API compatibility." )
86+ public String timeoutUnit = "MINUTES" ;
87+
7488 // it should be LockStep() - without params. But keeping this for backward compatibility
7589 // so `lock('resource1')` still works and `lock(label: 'label1', quantity: 3)` works too (resource
7690 // is not required)
@@ -154,6 +168,24 @@ public void setExtra(@CheckForNull List<LockStepResource> extra) {
154168 this .extra = extra ;
155169 }
156170
171+ @ DataBoundSetter
172+ public void setTimeoutForAllocateResource (long timeoutForAllocateResource ) {
173+ this .timeoutForAllocateResource = Math .max (0 , timeoutForAllocateResource );
174+ }
175+
176+ @ DataBoundSetter
177+ public void setTimeoutUnit (String timeoutUnit ) {
178+ if (timeoutUnit != null && !timeoutUnit .trim ().isEmpty ()) {
179+ // Validate it is a valid TimeUnit name
180+ try {
181+ java .util .concurrent .TimeUnit .valueOf (timeoutUnit .toUpperCase (Locale .ENGLISH ));
182+ } catch (IllegalArgumentException e ) {
183+ throw new IllegalArgumentException ("Invalid timeoutUnit: " + timeoutUnit );
184+ }
185+ this .timeoutUnit = timeoutUnit .toUpperCase (Locale .ENGLISH );
186+ }
187+ }
188+
157189 @ Extension
158190 public static final class DescriptorImpl extends StepDescriptor {
159191
@@ -229,6 +261,20 @@ public static FormValidation doCheckResourceSelectStrategy(
229261 return FormValidation .ok ();
230262 }
231263
264+ @ RequirePOST
265+ public ListBoxModel doFillTimeoutUnitItems (@ AncestorInPath Item item ) {
266+ if (item != null ) {
267+ item .checkPermission (Item .CONFIGURE );
268+ } else {
269+ Jenkins .get ().checkPermission (Jenkins .ADMINISTER );
270+ }
271+ ListBoxModel items = new ListBoxModel ();
272+ items .add ("Seconds" , "SECONDS" );
273+ items .add ("Minutes" , "MINUTES" );
274+ items .add ("Hours" , "HOURS" );
275+ return items ;
276+ }
277+
232278 @ Override
233279 public Set <Class <?>> getRequiredContext () {
234280 return Collections .singleton (TaskListener .class );
0 commit comments