-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DevBox] Start the Dev Box while configuring #273
base: main
Are you sure you want to change the base?
Conversation
{ | ||
throw new InvalidOperationException(Resources.GetResource(NotRunningFailedKey)); | ||
} | ||
await HandleNonRunningState(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if we could just call the IComputeSystem StartAsync() method instead since that starts a threadpool timer that wakes up every minute to check the progress of the operation. If we pass the DevBoxInstance to the WingetConfigWrapper then we'd be able to do that. Then we could use a wait event handle within a while loop that waits every minute.
Something like this e.g
if (_devBox.GetState() != ComputeSystemState.Running))
{
await _devBox.StartAsync(string.Empty);
var startCancellationTokenSource = new CancellationTokenSource();
startCancellationTokenSource.CancelAfter(TimeSpan.FromMinutes(30));
while (_devBoxStartEvent.WaitOne(TimeSpan.FromMinutes(1)))
{
if (_devBox.GetState() == ComputeSystemState.Running)
{
break;
}
if (startCancellationTokenSource.IsCancellationRequested)
{
throw new InvalidOperationException(Resources.GetResource(DevBoxErrorStateKey))
}
}
}
This would reduce the code amount by a good amount I believe. You can either use a ManualResetEvent or a Task.Delay like you've been using, but you'd have to have an extra variable to keep the loop alive. Also note, we need to increase the time Dev Home's configuration waits too here: https://github.com/microsoft/devhome/blob/ca1ca04bac3325bc68e29f8f478453d2b4f85971/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs#L419
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1. One question: would we send _devBoxStartEvent event if the device is already running by the time code in _devBox.StartAsync actually runs (since everything is async and in the cloud the device state can change between our last check and Start command)? This is probably not an issue since we check state every minute which, I assume, would be updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea; changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sshilov7 I just wanted to let you know that your assumption is right. Although that got me thinking of one more edge case:
- If the
_devBox.StartAsync
method returns an error then we'd be waiting for 15 minutes for no reason. @huzaifa-d, could you add an error check for this one?
private async Task HandleNonRunningState() | ||
{ | ||
// Check if the dev box might have been started in the meantime | ||
var stateResult = await _devBox.GetStateAsync(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should use GetState() too so we don't need to await it
ConfigurationSetStateChanged?.Invoke(this, new(new(ConfigurationSetChangeEventType.SetStateChanged, ConfigurationSetState.StartingDevice, ConfigurationUnitState.Unknown, null, null))); | ||
|
||
// Wait for the Dev Box to start with an initial wait of 3 minutes and a max of 15 minutes | ||
var delay = TimeSpan.FromSeconds(30); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could use the HalfMinutePeriod in the constants we're adding in this PR for this.
{ | ||
throw new InvalidOperationException(Resources.GetResource(DevBoxErrorStateKey)); | ||
} | ||
else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we probably don't need to wrap this in an else statement since throwing would exist the method
<value>The Dev Box isn't running. Please start the Dev Box and try again.</value> | ||
<comment>Error shown when the operation fails due to the Dev Box not currently running.</comment> | ||
<data name="DevBox_ErrorStateKey" xml:space="preserve"> | ||
<value>The Dev Box isn't in a valid state</value> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should say something like "{0} couldn't be started. Please try starting the Dev Box manually and try again."
where {0} is the name of the Dev Box
{ | ||
throw new InvalidOperationException(Resources.GetResource(NotRunningFailedKey)); | ||
} | ||
await HandleNonRunningState(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sshilov7 I just wanted to let you know that your assumption is right. Although that got me thinking of one more edge case:
- If the
_devBox.StartAsync
method returns an error then we'd be waiting for 15 minutes for no reason. @huzaifa-d, could you add an error check for this one?
// Wait for the Dev Box to start with an initial wait of 3 minutes and a max of 15 minutes | ||
var delay = TimeSpan.FromSeconds(30); | ||
var waitTimeLeft = TimeSpan.FromMinutes(12); | ||
await Task.Delay(TimeSpan.FromMinutes(3)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this 3-minute wait? Are chances that VM can start earlies so low? The code below checks the state once in 30 seconds. I wouldn't think sending 1 request per 30 seconds is too often.
Summary of the pull request
The PR addresses the issue where the Dev Box was no running while trying to apply a configuration. The Dev Box is now started, instead of erroring out.
##Before
##After
Validation steps performed
Manually
PR checklist