Forum Discussion

tcboeira's avatar
tcboeira
Brass Contributor
Jul 10, 2023

Possibility of Script that works with a load of data loop by loop - or from time to time

Hello Guys

 

Well, I don't know how to explain it, but I'll try, I hope I succeed ...

 

 Today I have a list of about 72,000 entries that I want to upload to my Exchange Online.

 

What I would like is for it to do for example... 5000, pause, +5000, pause, +5000, until the end.

 

An old Exchange module, for example, allows connections with a time of 30 minutes.

 

6. And with that, I know that there are - but I haven't seen - Script constructions that do more or less this... Loads 72,000, performs treatment for up to 30 minutes... then disconnects/reconnects and performs a new treatment for up to 30 minutes, and repeat this until the end, but always taking advantage of the same load. Somehow there's a mark on what's already been processed that it restarts every time from what hasn't.

 

I imagine that the concept, the idea, is the same.

 

I would like - if it's not too much trouble - to understand how to build, or find, a code snippet, an entire script that does something in this sense to deepen the study and adapt to my needs

 

Many, many thanks for everyone's attention and help!

2 Replies

  • tcboeira 

     

    There are a few ways that you could approach this, depending on the input source, you could look to add a field/column to the source data/file that includes a Boolean "processed" flag, which your script would update after your script logic completes

     

    An alternative method might be to load your input data, take a count of the total items/rows and maintain an "index" of the current item/row being processed... this index would get incremented after each item is processed

  • FranciscoNabas's avatar
    FranciscoNabas
    Copper Contributor
    Hey there!

    In this case if you are sure the connection time limit is 30 minutes, I recommend using something that measures time.
    This would be my approach:

    - Create a PowerShell runspace and instance to run the workload asynchronously.
    - Start a System.Diagnostics.StopWatch
    - Enter a while loop that checks the execution of the PowerShell instance, and times out after 30 minutes.

    However, there is a chance of your script terminate the execution in the middle of an item processing, which in this case it's better to use item count.

    Here's a sketch. Mind that this was not tested, and you need to adjust to your needs.

    $bigList = @(<# Your 72,000 items list #>)

    # Creating a Runspace Pool to hold our PowerShell 'threads'.
    $pool = [runspacefactory]::CreateRunspacePool()
    $pool.ApartmentState = 'STA'
    $pool.Open()

    # Create a synchronized hash table to exchange data between the current and new threads.
    $messenger = [hashtable]::Synchronized(@{
    Processed = [System.Collections.ArrayList]@()
    Pending = $null
    })

    while ($messenger.Processed.Count -lt $bigList.Count) {

    # Separate the items you already processed. You might have to adjust this according
    # to the complexity of your object list.
    $messenger.Pending = $bigList | Where-Object { $_ -notin $messenger.Processed }

    # Creating the PowerShell instance.
    $powerShell = [powershell]::Create()
    $powerShell.RunspacePool = $pool
    [void]$powerShell.AddScript({

    param ($Messenger)

    foreach ($item in $Messenger.Pending) {
    <#
    Your logic goes here. We used the messenger to retrieve the pending items to process.
    After you finish processing each item, add it to the 'Processed' property from the
    messenger:

    $messenger.Processed.Add($item)
    #>
    }
    })

    # Passing the messenger as a parameter.
    [void]$powerShell.AddParameter('Messenger', $messenger)

    # Starting the instance asynchronously
    $handle = $powerShell.BeginInvoke()


    # Here is your main while loop. You can wait 'X' amount of time, or 'X' itens processed, while monitoring
    # the messenger processed list. If you choose time, use a StopWatch.

    $stopWatch = [System.Diagnostics.Stopwatch]::StartNew()
    do {

    # Check the instance execution.
    if ($powerShell.InvocationStateInfo.State -ne 'Running') {
    break
    }

    } while ($stopWatch.Elapsed.TotalMinutes -le 30)

    # Dispose of the PowerShell instance. This is important to avoid resource leak.
    # If you care about the outcome, assign a variable instead of [void]~.
    [void]$powerShell.EndInvoke($handle)
    $powerShell.Dispose()
    }

    # Clenup the pool as well
    $pool.Dispose()

Resources