[UGS] New users failing initial workspace sync due to perforce query hitting max results limit

New UGS are being presented a perforce exception when syncing for the first time, this seems to be because of our MaxResult limit in our perforce user groups. We use this limit to prevent unchecked queries taking out our perforce server.

Having checked the code, I cannot see a way around this so I’ve got a change to optionally restrict this sync to the last code change within N number of changes so that UGS can complete it’s first initial sync.

Steps to Reproduce

  1. Set perforce group to enforce MaxResults
  2. Open UGS
  3. Ensure …/.ugs/state.json has “CurrentChangeNumber” & “CurrentCodeChangeNumber” set to -1
  4. Attempt to sync to content code change
EpicGames.Perforce.PerforceException
  HResult=0x80131500
  Message=Failed: Request too large (over 2500000); see 'p4 help maxresults'. (Generic=Admin)
  Source=EpicGames.Perforce
  StackTrace:
   at EpicGames.Perforce.PerforceResponse`1.get_Data() in D:\***\Engine\Source\Programs\Shared\EpicGames.Perforce\PerforceResponse.cs:line 149
   at EpicGames.Perforce.PerforceResponseList`1.<>c.<get_Data>b__7_1(PerforceResponse`1 x) in D:\***\Engine\Source\Programs\Shared\EpicGames.Perforce\PerforceResponseList.cs:line 56
   at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
   at System.Linq.Enumerable.WhereEnumerableIterator`1.ToList()
   at EpicGames.Perforce.PerforceResponseList`1.get_Data() in D:\***\Engine\Source\Programs\Shared\EpicGames.Perforce\PerforceResponseList.cs:line 56
   at EpicGames.Perforce.PerforceConnectionExtensions.<GetChangesAsync>d__25.MoveNext() in D:\***\Engine\Source\Programs\Shared\EpicGames.Perforce\PerforceConnection.cs:line 928
   at UnrealGameSync.Utility.<EnumerateChanges>d__6.MoveNext() in D:\ ***\Engine\Source\Programs\UnrealGameSync\UnrealGameSyncShared\Utility.cs:line 191
   at UnrealGameSync.Utility.<EnumerateChanges>d__6.System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult(Int16 token)
   at System.Linq.AsyncEnumerable.SelectEnumerableAsyncIterator`2.<MoveNextCore>d__7.MoveNext()
   at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable`1.ConfiguredValueTaskAwaiter.GetResult()
   at System.Linq.AsyncIteratorBase`1.<MoveNextAsync>d__8.MoveNext()
   at System.Linq.AsyncIteratorBase`1.<MoveNextAsync>d__8.MoveNext()
   at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
   at UnrealGameSync.Utility.<EnumerateChangeDetails>d__8.MoveNext() in D:\***\Engine\Source\Programs\UnrealGameSync\UnrealGameSyncShared\Utility.cs:line 277
   at UnrealGameSync.Utility.<EnumerateChangeDetails>d__8.MoveNext() in D:\***\Engine\Source\Programs\UnrealGameSync\UnrealGameSyncShared\Utility.cs:line 339
   at UnrealGameSync.Utility.<EnumerateChangeDetails>d__8.System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult(Int16 token)
  This exception was originally thrown at this call stack:
    EpicGames.Perforce.PerforceResponse<T>.Data.get() in PerforceResponse.cs
    EpicGames.Perforce.PerforceResponseList<T>.get_Data.AnonymousMethod__7_1(EpicGames.Perforce.PerforceResponse<T>) in PerforceResponseList.cs
    [External Code]
    EpicGames.Perforce.PerforceResponseList<T>.Data.get() in PerforceResponseList.cs
    EpicGames.Perforce.PerforceConnectionExtensions.GetChangesAsync(EpicGames.Perforce.IPerforceConnection, EpicGames.Perforce.ChangesOptions, int, EpicGames.Perforce.ChangeStatus, EpicGames.Perforce.FileSpecList, System.Threading.CancellationToken) in PerforceConnection.cs
    UnrealGameSync.Utility.EnumerateChanges(EpicGames.Perforce.IPerforceConnection, System.Collections.Generic.IEnumerable<string>, int?, int?, int?, System.Threading.CancellationToken) in Utility.cs
    [External Code]
    UnrealGameSync.Utility.EnumerateChangeDetails(EpicGames.Perforce.IPerforceConnection, System.Collections.Generic.IAsyncEnumerable<int>, System.Collections.Generic.IEnumerable<string>, System.Threading.CancellationToken) in Utility.cs
    UnrealGameSync.Utility.EnumerateChangeDetails(EpicGames.Perforce.IPerforceConnection, System.Collections.Generic.IAsyncEnumerable<int>, System.Collections.Generic.IEnumerable<string>, System.Threading.CancellationToken) in Utility.cs




Hi Jordan,

Internally we bump up the maxresults field to avoid this issue.

There are some other perforce fields you could play with to try to protect server performance, but I suspect you will hit similar limitations:

https://help.perforce.com/helix\-core/server\-apps/p4sag/2022\.2/Content/P4SAG/performance.prevention.query\_limits.html

Beyond increasing maxresults there are a few other options:

  • Reducing the client view we are querying => since this would pull less results
  • Adding a cap to the query i.e. your proposed fix of limiting the minChangeNumber

Your fix of adding a CodeChangeListSearchRange looks reasonable to me, let me know if this works.

Hope this helps.

That’s great news.

We have the PR tracked internally, I’ll raise it in our weekly UGS meeting to discuss potentially merging it into a release.

Hi Raymond,

Apologies for the late response, I will be sure to look at these other option and get back to you here.

Can confirm the change stops these exceptions throwing, we’ve rolled this out to a few devs internally and have had no issues.

Thanks again!