Skip to content

Commit c1b2d78

Browse files
committed
Fix issues with job state changes when cmdlet is blocking, and refactor long running job tests for robustness
1 parent 537b99a commit c1b2d78

File tree

2 files changed

+170
-102
lines changed

2 files changed

+170
-102
lines changed

src/Common/Commands.Common/AzureLongRunningJob.cs

Lines changed: 71 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,59 @@
2626

2727
namespace Microsoft.Azure.Commands.Common
2828
{
29-
public class AzureLongRunningJob<T> : Job, ICommandRuntime where T : AzurePSCmdlet
29+
/// <summary>
30+
/// Abstract class for uniform processing of jobs
31+
/// </summary>
32+
public abstract class AzureLongRunningJob : Job
33+
{
34+
protected AzureLongRunningJob(string command, string name) : base(command, name)
35+
{
36+
}
37+
38+
/// <summary>
39+
/// Run a cmdlet execution as a Job - this is intended to run in a background thread
40+
/// </summary>
41+
/// <param name="state">The Job record that will track the progress of this job </param>
42+
public abstract void RunJob(object state);
43+
44+
/// <summary>
45+
/// Return cmdlet runtime that will report results to this job
46+
/// </summary>
47+
/// <returns>An IcommandRuntime that reports results to this job</returns>
48+
public abstract ICommandRuntime GetJobRuntime();
49+
50+
/// <summary>
51+
/// Mark the job as started
52+
/// </summary>
53+
public abstract bool TryStart();
54+
55+
/// <summary>
56+
/// Mark the job as Blocked
57+
/// </summary>
58+
public abstract bool TryBlock();
59+
60+
61+
/// <summary>
62+
/// Complete the job (will mark job as Completed or Failed, depending on the execution details)
63+
/// </summary>
64+
public abstract void Complete();
65+
66+
/// <summary>
67+
/// Mark the Job as Failed
68+
/// </summary>
69+
public abstract void Fail();
70+
71+
/// <summary>
72+
/// Stop the job
73+
/// </summary>
74+
public abstract void Cancel();
75+
}
76+
77+
/// <summary>
78+
/// Cmdlet-specific Implementation class for long running jobs
79+
/// </summary>
80+
/// <typeparam name="T">The type of the cmdlet being executed</typeparam>
81+
public class AzureLongRunningJob<T> : AzureLongRunningJob, ICommandRuntime where T : AzurePSCmdlet
3082
{
3183
string _status = "Running";
3284
T _cmdlet;
@@ -204,7 +256,7 @@ public static U CopyCmdlet<U>(U cmdlet) where U : AzurePSCmdlet
204256
/// Run a cmdlet execution as a Job - this is intended to run in a background thread
205257
/// </summary>
206258
/// <param name="state">The Job record that will track the progress of this job </param>
207-
public virtual void RunJob(object state)
259+
public override void RunJob(object state)
208260
{
209261
if (TryStart())
210262
{
@@ -240,7 +292,7 @@ public virtual void RunJob(object state)
240292
/// Return cmdlet runtime that will report results to this job
241293
/// </summary>
242294
/// <returns>An IcommandRuntime that reports results to this job</returns>
243-
public virtual ICommandRuntime GetJobRuntime()
295+
public override ICommandRuntime GetJobRuntime()
244296
{
245297
return this as ICommandRuntime;
246298
}
@@ -308,7 +360,7 @@ internal string GetShouldMethodFailureReaon(T cmdlet, ShouldMethodStreamItem met
308360
/// <summary>
309361
/// Mark the task as started
310362
/// </summary>
311-
public bool TryStart()
363+
public override bool TryStart()
312364
{
313365
bool result = false;
314366
lock (_lockObject)
@@ -327,7 +379,7 @@ public bool TryStart()
327379
/// <summary>
328380
/// Mark the task as blocked
329381
/// </summary>
330-
public bool TryBlock()
382+
public override bool TryBlock()
331383
{
332384
bool result = false;
333385
lock (_lockObject)
@@ -346,7 +398,7 @@ public bool TryBlock()
346398
/// <summary>
347399
/// Mark the job as Failed
348400
/// </summary>
349-
public void Fail()
401+
public override void Fail()
350402
{
351403
lock (_lockObject)
352404
{
@@ -358,7 +410,7 @@ public void Fail()
358410
/// <summary>
359411
/// Mark the job as successfully complete
360412
/// </summary>
361-
public void Complete()
413+
public override void Complete()
362414
{
363415
lock (_lockObject)
364416
{
@@ -379,7 +431,7 @@ public void Complete()
379431
/// <summary>
380432
/// Mark the job as cancelled
381433
/// </summary>
382-
public void Cancel()
434+
public override void Cancel()
383435
{
384436
lock (_lockObject)
385437
{
@@ -788,8 +840,7 @@ private bool InvokeShouldMethodAndWaitForResults(Func<Cmdlet, bool> shouldMethod
788840
try
789841
{
790842
stateChangedEventHandler(null, new JobStateEventArgs(this.JobStateInfo));
791-
792-
if (!gotResultEvent.IsSet && this.TryBlock())
843+
if (!gotResultEvent.IsSet)
793844
{
794845
WriteDebug(string.Format(Resources.TraceBlockLROThread, methodType));
795846
ShouldMethodInvoker methodInvoker = new ShouldMethodInvoker
@@ -801,16 +852,18 @@ private bool InvokeShouldMethodAndWaitForResults(Func<Cmdlet, bool> shouldMethod
801852
};
802853

803854
BlockedActions.Enqueue(new ShouldMethodStreamItem(methodInvoker));
804-
805-
gotResultEvent.Wait();
806-
WriteDebug(string.Format(Resources.TraceUnblockLROThread, shouldMethod));
807-
TryStart();
808-
lock (resultsLock)
855+
if (this.TryBlock())
809856
{
810-
if (closureSafeExceptionThrownOnCmdletThread == null) // stateChangedEventHandler didn't set the results? = ok to clobber results?
857+
gotResultEvent.Wait();
858+
WriteDebug(string.Format(Resources.TraceUnblockLROThread, shouldMethod));
859+
TryStart();
860+
lock (resultsLock)
811861
{
812-
closureSafeExceptionThrownOnCmdletThread = methodInvoker.ThrownException;
813-
methodResult = methodInvoker.MethodResult;
862+
if (closureSafeExceptionThrownOnCmdletThread == null) // stateChangedEventHandler didn't set the results? = ok to clobber results?
863+
{
864+
closureSafeExceptionThrownOnCmdletThread = methodInvoker.ThrownException;
865+
methodResult = methodInvoker.MethodResult;
866+
}
814867
}
815868
}
816869
}

0 commit comments

Comments
 (0)