public async Task LaunchBuildServerInfoFetchOperationAsync() { await TaskScheduler.Default; CancelBuildStatusFetchOperation(); var launchToken = _launchCancellation.Next(); var buildServerAdapter = await GetBuildServerAdapterAsync().ConfigureAwait(false); await _revisionGridView.SwitchToMainThreadAsync(launchToken); _buildServerAdapter?.Dispose(); _buildServerAdapter = buildServerAdapter; await TaskScheduler.Default; if (buildServerAdapter == null || launchToken.IsCancellationRequested) { return; } var scheduler = NewThreadScheduler.Default; // Run this first as it (may) force start queries var runningBuildsObservable = buildServerAdapter.GetRunningBuilds(scheduler); var fullDayObservable = buildServerAdapter.GetFinishedBuildsSince(scheduler, DateTime.Today - TimeSpan.FromDays(3)); var fullObservable = buildServerAdapter.GetFinishedBuildsSince(scheduler); var fromNowObservable = buildServerAdapter.GetFinishedBuildsSince(scheduler, DateTime.Now); var isBuildRunning = false; var cancellationToken = new CompositeDisposable { fullDayObservable.OnErrorResumeNext(fullObservable) .OnErrorResumeNext(Observable.Empty <BuildInfo>() .DelaySubscription(TimeSpan.FromMinutes(1)) .OnErrorResumeNext(fromNowObservable) .Retry() .Repeat()) .ObserveOn(MainThreadScheduler.Instance) .Subscribe(OnBuildInfoUpdate), runningBuildsObservable.Do(_ => isBuildRunning = true) .Finally(() => { Thread.Sleep(TimeSpan.FromSeconds(isBuildRunning ? PollIntervalWhenSomeBuildsAreRunning : PollIntervalWhenNoBuildsAreRunning)); isBuildRunning = false; }) .Retry() .Repeat() .ObserveOn(MainThreadScheduler.Instance) .Subscribe(OnBuildInfoUpdate) }; await _revisionGridView.SwitchToMainThreadAsync(launchToken); CancelBuildStatusFetchOperation(); _buildStatusCancellationToken = cancellationToken; }
public async Task LaunchBuildServerInfoFetchOperationAsync() { await TaskScheduler.Default; CancelBuildStatusFetchOperation(); var launchToken = _launchCancellation.Next(); var buildServerAdapter = await GetBuildServerAdapterAsync().ConfigureAwait(false); await _revisionGridView.SwitchToMainThreadAsync(launchToken); _buildServerAdapter?.Dispose(); _buildServerAdapter = buildServerAdapter; await TaskScheduler.Default; if (buildServerAdapter == null || launchToken.IsCancellationRequested) { return; } var scheduler = NewThreadScheduler.Default; // Run this first as it (may) force start queries var runningBuildsObservable = buildServerAdapter.GetRunningBuilds(scheduler); var fullDayObservable = buildServerAdapter.GetFinishedBuildsSince(scheduler, DateTime.Today - TimeSpan.FromDays(3)); var fullObservable = buildServerAdapter.GetFinishedBuildsSince(scheduler); bool anyRunningBuilds = false; var delayObservable = Observable.Defer(() => Observable.Empty <BuildInfo>() .DelaySubscription(anyRunningBuilds ? ShortPollInterval : LongPollInterval)); var shouldLookForNewlyFinishedBuilds = false; DateTime nowFrozen = DateTime.Now; // All finished builds have already been retrieved, // so looking for new finished builds make sense only if running builds have been found previously var fromNowObservable = Observable.If(() => shouldLookForNewlyFinishedBuilds, buildServerAdapter.GetFinishedBuildsSince(scheduler, nowFrozen) .Finally(() => shouldLookForNewlyFinishedBuilds = false)); var cancellationToken = new CompositeDisposable { fullDayObservable.OnErrorResumeNext(fullObservable) .OnErrorResumeNext(Observable.Empty <BuildInfo>() .DelaySubscription(TimeSpan.FromMinutes(1)) .OnErrorResumeNext(fromNowObservable) .Retry() .Repeat()) .ObserveOn(MainThreadScheduler.Instance) .Subscribe(OnBuildInfoUpdate), runningBuildsObservable.Do(buildInfo => { anyRunningBuilds = true; shouldLookForNewlyFinishedBuilds = true; }) .Retry() .Concat(delayObservable) .Finally(() => anyRunningBuilds = false) .Repeat() .ObserveOn(MainThreadScheduler.Instance) .Subscribe(OnBuildInfoUpdate) }; await _revisionGridView.SwitchToMainThreadAsync(launchToken); CancelBuildStatusFetchOperation(); _buildStatusCancellationToken = cancellationToken; }