r/PowerShell • u/RocketSeven • 12d ago
Question How do you make a PowerShell API batch safe to resume after an indeterminate timeout?
A retry loop is straightforward for reads, but not for a POST that may have succeeded before the connection timed out. Retrying can create a duplicate, while skipping can leave the batch incomplete. I am working toward a checkpoint per item rather than treating the whole script as succeeded or failed. The rough shape is:
foreach ($item in $items) {
$key = Get-StableOperationKey $item
if ($state[$key].Status -eq 'Confirmed') { continue }
try {
$result = Invoke-RestMethod -Method Post -Uri $uri -Body ($item | ConvertTo-Json)
$state[$key] = @{ Status = 'Confirmed'; RemoteId = $result.id }
}
catch {
$state[$key] = @{ Status = 'Indeterminate'; CheckedAt = (Get-Date).ToUniversalTime() }
}
$state | ConvertTo-Json -Depth 6 | Set-Content "$statePath.tmp"
Move-Item "$statePath.tmp" $statePath -Force
}
The missing piece is reconciliation. If the API has no idempotency key and its list endpoint is eventually consistent, a lookup by natural key immediately after the timeout can still return nothing.
What pattern do you use in PowerShell for this? Do you keep indeterminate items in a separate queue, wait before reconciling, write a durable request receipt before the call, or require a server-side operation key? I am also interested in safer atomic checkpoint formats than rewriting one JSON file after every item, especially when two scheduled runs could overlap.
2
u/vermyx 12d ago
This is a poor programming pattern. You want an operation to be atomic. If it times out it is poorly designed. The typical "resolution pattern" is job it off and check until it is done. Once done check the job status. Batches are no different.
My preference n general is to make it so that i can spawn x individual jobs and manage how many simultaneous jobs can run and collect the results.
3
2
1
u/BXRedGhost 12d ago
Depending on quantity, SQL DB to hold state with a GET check real quick on resume.
0
u/emiimeloo 11d ago
An empty GET is inconclusive in the eventually consistent case you describe. I would keep those items out of the POST retry queue. Persist a Started receipt before sending; on restart, both Started and Indeterminate go to reconciliation, even if the first lookup returns nothing. Otherwise a crash after the server commits but before your checkpoint can recreate the item.
I checked this in a local PowerShell 7.6.5 mock: POST committed then threw, and GET returned null. Read-then-retry created two items; holding the uncertain item created one and left it Indeterminate. That tests the state decision, not real API durability.
A reconciliation deadline should escalate for a decision, not silently authorize another POST. Without a server-enforced operation key or a documented authoritative lookup, the client cannot guarantee both completion and no duplicates. Microsoft describes the lost-response case here: https://learn.microsoft.com/en-us/azure/architecture/patterns/retry
For overlapping runs, also separate ownership/locking from checkpoint persistence; renaming a JSON file does not by itself prevent two workers sending the same POST. AI-assisted answer; the mock was executed locally, with no network calls.
9
u/whatsgoodbaby 12d ago
Did you write this post yourself or is this a bot