Monday, January 31, 2011

Dealing with Throttling restrictions in Exchange Web Services on Exchange 2010 SP1 in scripts and code

In Exchange 2010 SP1 throttling is enabled by default and while for the best part this is a good thing there are a few things you may need to be careful of if you have written code that retrieves a large number of items from a mailbox folder.

While you can disable or set custom throttling polices for your application or scripts its generally a better idea to build your code to work within these throttling thresholds. With EWS the throttling policies affect a number of different areas from the number of concurrent connections one user can establish to a server, limits on the number of subscriptions and also the CPU time one particular user can consume when executing particular operations. For the most part if your using simple single threaded scripts where your not executing requests concurrently most of the settings wont have any bearing. The one policy setting that will have a direct affect on existing scripts or code is the EWSFindCountLimit which by default is limited to 1000. This is discussed in a little more detail here

The upshot of this is if you have code where you have set a page size greater than 1000 and your not checking IncludesLastItemInRange to ensure you have retrieved all the items within the scope of your findItems or findfolder request then your current code may will only retrieve the first 1000 items in a folder .To cater for this if your using Powershell and the EWS Managed API you need to use something like a Do{}(Where) to write code loop to ensure you make followup finditem/findfolder requests to retrieve all the items from a particular folder. For example to loop through all the messages within an inbox using a pagesize of 1000 would look like

$folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
$ivItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000)
$fiResult = ""
$fiResult = $Service.FindItems($folderid,$ivItemView)
foreach($Items in $fiResult.Items){
$ivItemView.offset += $fiResult.Items.Count
}while($fiResult.MoreAvailable -eq $true)

The other setting to be careful of is the EWSFastSearchTimeoutInSeconds which is set to 60 seconds by default. If your querying folders with a large number of items with complex filters then this could be a problem. Fortunately the Entry point EWS offers to make Exchange Search queries should help counter problems with this.