This is one way to create a polling loop in PowerShell. I’m sure there are several options, but this one works well for the use case.
Backstory
I needed to start the refresh of a data model using the new Start-RsRestCacheRefreshPlan function I created, and then check a few seconds later to make sure it had started, using the Get-RsRestCacheRefreshPlanHistory function. Sounds easy enough right? The problem is that the service doesn’t update instantly to tell you that it had started. Also, the service sometimes takes longer, depending on load.
Start-Sleep isn’t ideal
Originally I had used the Start-Sleep command to wait 3 seconds ( Start-Sleep 3
). That worked fine on my machine, but when I deployed it to the server, I found I needed to bump it up to 6 seconds. At first that worked, but then a week later I needed to bump it up to 9 seconds. The problem here is obvious, if we force it to wait 9 seconds every time, even if the task was updated after 4 second, we’re wasting extra time. And those seconds are going to add up.
Instead, I was asked to allow the Get-RsRestCacheRefreshPlanHistory function to wait up to 15 seconds to get the answer it was looking for, but to stop as soon as it got the right answer. In this particular case @($someHistory).count -eq 1
is the “right answer”. But if it takes more than 15 seconds, then we just assume failure.
How to WHILE
The only problem with this request for me to “use a polling loop” was that I didn’t quite remember off the top of my head how to do something like this. So I pinged Doug Finke ( b | t ) and about 18 seconds later I had my solution.
Stepping through the logic
- First, we need to start the refresh
- Next, we find out what time it is
- Now we need to check the .count property of the $someHistory variable and see if it is less than 1, as soon as the .count property is 1 or more, the loop will stop
- The first time we do this check the variable will be empty, and will therefore be less than 1
- If we pass that check, we then go ahead and run our command to check the history and load the result of that check into the $someHistory variable
- Next, we check the current time and see if 15 seconds have elapsed yet. If 15 seconds have elapsed we run whatever the code inside the {} is, in this case it’s break keyword which is the other way we can end our loop.
- If we get all the way down to that last little } and neither of our conditions have been met, we just start the whole loop over again.
Here’s that chink of code again in case you need to build something similar.
Start-RsRestCacheRefreshPlan
$timer= Get-Date
while ((@($someHistory).count -lt 1)) {
$someHistory = Get-RsRestCacheRefreshPlanHistory –RsReport “/ReportCatalog”
if(((Get-Date)–$timer).seconds -ge 15) {break}
}
We can finally do our check to see if @($someHistory).count -eq 1
and move on to the next step in our command.
Again, this is just the solution that worked well for me. If you know of an easier way to do this kind of polling, please share it in the comments
Until someone shows me a better way, I’m going to use this same technique to wait for my SQL Servers to be ready when I build them in Docker.
The post Create a Polling Loop in PowerShell first appeared on SQLvariations: SQL Server, a little PowerShell, maybe some Power BI.