private/projectDatabase/project_database_Async.ps1
function Sync-ProjectDatabaseAsync { [CmdletBinding()] [OutputType([bool])] param( [Parameter()][string]$Owner, [Parameter()][int]$ProjectNumber, [Parameter()][int]$SyncBatchSize = 30 ) ($Owner, $ProjectNumber) = Get-OwnerAndProjectNumber -Owner $Owner -ProjectNumber $ProjectNumber if ([string]::IsNullOrWhiteSpace($owner) -or [string]::IsNullOrWhiteSpace($ProjectNumber)) { "Owner and ProjectNumber are required" | Write-MyError; return $null } if (! $(Test-ProjectDatabaseStaged -Owner $Owner -ProjectNumber $ProjectNumber)) { "Nothing to commit" | Write-MyHost return } $db = Get-Project -Owner $Owner -ProjectNumber $ProjectNumber $stagedItemsCount = $db.Staged.Keys.Count # Send update to project $db = Sync-ProjectAsync -Database $db -SyncBatchSize $SyncBatchSize # Saved changes to database Save-ProjectDatabaseSafe -Database $db if (Test-ProjectDatabaseStaged -Owner $Owner -ProjectNumber $ProjectNumber) { "Still pending staged values" | Write-MyError return $false } else { "All ($stagedItemsCount) staged values synced" | Write-MyHost return $true } } function Sync-ProjectAsync { [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Position = 0)][object]$Database, [Parameter()][int]$SyncBatchSize = 30 ) $db = $Database $calls = @() $callsBatch = @() $ItemsStagedId = $db.Staged.Keys | Copy-MyStringArray foreach ($itemId in $ItemsStagedId) { $itemStaged = $db.Staged.$itemId $FieldStagedId = $itemStaged.Keys | Copy-MyStringArray foreach ($fieldId in $FieldStagedId) { $value = $itemStaged.$fieldId.Value $field = $itemStaged.$fieldId.Field # Staged has the display value. Convert to the update value $valueToSend = ConvertTo-FieldValue -Field $field -Value $value $params = @{ Database = $db ItemId = $itemId FieldId = $fieldId FieldName = $field.name FieldType = $field.type FieldDataType = $field.dataType Value = $valueToSend } # "Calling [$($params.Database.ProjectId)/$($params.ItemId)/$($params.FieldId) ($($params.FieldType)) = $($params.Value) ] ..." | Write-MyHost -NoNewLine $call = Update-ProjectItem @params -Async $calls += $call $callsBatch += $call # Call batch size if we reached the maximum batch size if ($callsBatch.count -eq $SyncBatchSize) { Waiting -Calls $callsBatch $callsBatch = @() # Reset the batch } } } #Remaining calls Waiting -Calls $callsBatch # Process all the calls foreach ($call in $calls) { if (! (Test-UpdateProjectItemAsyncCall $call) ) { "Updating Project Item call Failed [$itemId/$fieldName/$value]" | Write-MyError continue } "Saving [$($call.projectId)/$($call.itemId)/$($call.FieldId) ($($call.FieldName)) = ""$($call.Value)"" ] ..." | Write-MyHost Set-ItemValue -Database $db -ItemId $call.itemId -FieldName $call.fieldName -Value $call.Value Remove-ItemStaged -Database $db -ItemId $call.itemId -FieldId $call.FieldId } "Done" | Write-MyHost return $db } function Waiting($Calls) { $waitingJobs = $Calls.job $all = $Calls.Count "Waiting for [$all] jobs to complete " | Write-MyHost -noNewline while ($waitingJobs.Count -ne 0) { $waitings = $waitingJobs | Wait-Job -Any "." | Write-MyHost -NoNewline # Remove completed jobs from the waiting list $waitingJobs = $waitingJobs | Where-Object { $_.Id -ne $waitings.Id } } $completed = $Calls | Where-Object { $_.job.State -eq 'Completed' } | Measure-Object | Select-Object -ExpandProperty Count $failed = $Calls | Where-Object { $_.job.State -eq 'Failed' } | Measure-Object | Select-Object -ExpandProperty Count $all = $Calls.Count "" | Write-MyHost "Completed [$completed] Failed [$failed]" | Write-MyHost } |