From 943836e37a4326369b27836136e9df2b24033c45 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 8 Nov 2016 10:47:05 +0100 Subject: [PATCH 1/3] Lazy load the services needed by UsageTracker. To improve the startup time of the extension. --- .../GitHub.VisualStudio.csproj | 1 + src/GitHub.VisualStudio/GitHubPackage.cs | 10 ++- .../Services/UsageTracker.cs | 64 +++++++++++-------- .../Services/UsageTrackerDispatcher.cs | 29 +++++++++ 4 files changed, 76 insertions(+), 28 deletions(-) create mode 100644 src/GitHub.VisualStudio/Services/UsageTrackerDispatcher.cs diff --git a/src/GitHub.VisualStudio/GitHub.VisualStudio.csproj b/src/GitHub.VisualStudio/GitHub.VisualStudio.csproj index a1b9ec9e56..9675136cca 100644 --- a/src/GitHub.VisualStudio/GitHub.VisualStudio.csproj +++ b/src/GitHub.VisualStudio/GitHub.VisualStudio.csproj @@ -298,6 +298,7 @@ + diff --git a/src/GitHub.VisualStudio/GitHubPackage.cs b/src/GitHub.VisualStudio/GitHubPackage.cs index 7d96b837cc..48cf2a3e58 100644 --- a/src/GitHub.VisualStudio/GitHubPackage.cs +++ b/src/GitHub.VisualStudio/GitHubPackage.cs @@ -52,8 +52,9 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke await base.InitializeAsync(cancellationToken, progress); await EnsurePackageLoaded(new Guid(ServiceProviderPackage.ServiceProviderPackageId)); - //var usageTracker = await GetServiceAsync(typeof(IUsageTracker)) as IUsageTracker; - //usageTracker.IncrementLaunchCount(); + // Activate the usage tracker by forcing an instance to be created. + await GetServiceAsync(typeof(IUsageTracker)); + InitializeMenus().Forget(); } @@ -178,6 +179,11 @@ async Task CreateService(IAsyncServiceContainer container, CancellationT var sp = await GetServiceAsync(typeof(IUIProvider)) as IUIProvider; return new MenuProvider(sp); } + else if (serviceType == typeof(IUsageTracker)) + { + var uiProvider = await GetServiceAsync(typeof(IUIProvider)) as IUIProvider; + return new UsageTracker(uiProvider); + } // go the mef route else { diff --git a/src/GitHub.VisualStudio/Services/UsageTracker.cs b/src/GitHub.VisualStudio/Services/UsageTracker.cs index b166b2c7fc..9e066e6347 100644 --- a/src/GitHub.VisualStudio/Services/UsageTracker.cs +++ b/src/GitHub.VisualStudio/Services/UsageTracker.cs @@ -14,20 +14,20 @@ namespace GitHub.Services { - [Export(typeof(IUsageTracker))] - [PartCreationPolicy(CreationPolicy.Shared)] public class UsageTracker : IUsageTracker { const string StoreFileName = "ghfvs.usage"; static readonly Calendar cal = CultureInfo.InvariantCulture.Calendar; + readonly IUIProvider uiProvider; + readonly DispatcherTimer timer; + IMetricsService client; - readonly IConnectionManager connectionManager; + IConnectionManager connectionManager; IPackageSettings userSettings; - readonly IVSServices vsservices; - readonly DispatcherTimer timer; - readonly string storePath; - readonly IServiceProvider serviceProvider; + IVSServices vsservices; + string storePath; + bool firstRun = true; Func fileExists; Func readAllText; @@ -35,13 +35,9 @@ public class UsageTracker : IUsageTracker Action dirCreate; [ImportingConstructor] - public UsageTracker( - IProgram program, - IConnectionManager connectionManager, - IVSServices vsservices, - [Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider) + public UsageTracker(IUIProvider uiProvider) { - this.serviceProvider = serviceProvider; + this.uiProvider = uiProvider; fileExists = (path) => System.IO.File.Exists(path); readAllText = (path, encoding) => @@ -65,17 +61,11 @@ public UsageTracker( }; dirCreate = (path) => System.IO.Directory.CreateDirectory(path); - this.connectionManager = connectionManager; - this.vsservices = vsservices; this.timer = new DispatcherTimer( - TimeSpan.FromMinutes(1), + TimeSpan.FromMinutes(3), DispatcherPriority.Background, TimerTick, Dispatcher.CurrentDispatcher); - this.storePath = System.IO.Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), - program.ApplicationName, - StoreFileName); RunTimer(); } @@ -145,8 +135,29 @@ public void IncrementLoginCount() SaveUsage(usage); } + void Initialize() + { + // The services needed by the usage tracker are loaded when they are first needed to + // improve the startup time of the extension. + if (userSettings == null) + { + client = uiProvider.GetService(); + connectionManager = uiProvider.GetService(); + userSettings = uiProvider.GetService(); + vsservices = uiProvider.GetService(); + + var program = uiProvider.GetService(); + storePath = System.IO.Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + program.ApplicationName, + StoreFileName); + } + } + UsageStore LoadUsage() { + Initialize(); + var json = fileExists(storePath) ? readAllText(storePath, Encoding.UTF8) : null; UsageStore result = null; try @@ -178,7 +189,6 @@ void RunTimer() { // The timer first ticks after 3 minutes to allow things to settle down after startup. // This will be changed to 8 hours after the first tick by the TimerTick method. - timer.Interval = TimeSpan.FromMinutes(3); timer.Start(); } @@ -194,21 +204,23 @@ void TimerTick(object sender, EventArgs e) async Task TimerTick() { - Debug.Assert(client != null, "TimerTick should not be triggered when there is no IMetricsService"); + Initialize(); - // Subsequent timer ticks should occur every 8 hours. - timer.Interval = TimeSpan.FromHours(8); + if (firstRun) + { + IncrementLaunchCount(); + timer.Interval = TimeSpan.FromHours(8); + firstRun = false; + } if (userSettings == null) { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); - client = serviceProvider.GetExportedValue(); if (client == null) { timer.Stop(); return; } - userSettings = serviceProvider.GetExportedValue(); } if (!userSettings.CollectMetrics) diff --git a/src/GitHub.VisualStudio/Services/UsageTrackerDispatcher.cs b/src/GitHub.VisualStudio/Services/UsageTrackerDispatcher.cs new file mode 100644 index 0000000000..b58d68de33 --- /dev/null +++ b/src/GitHub.VisualStudio/Services/UsageTrackerDispatcher.cs @@ -0,0 +1,29 @@ +using Microsoft.VisualStudio.Shell; +using System; +using System.ComponentModel.Composition; + +namespace GitHub.Services +{ + [Export(typeof(IUsageTracker))] + [PartCreationPolicy(CreationPolicy.NonShared)] + public class UsageTrackerDispatcher : IUsageTracker + { + readonly IUsageTracker inner; + + [ImportingConstructor] + public UsageTrackerDispatcher([Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider) + { + inner = serviceProvider.GetService(typeof(IUsageTracker)) as IUsageTracker; + } + + public void IncrementCloneCount() => inner.IncrementCloneCount(); + public void IncrementCreateCount() => inner.IncrementCreateCount(); + public void IncrementCreateGistCount() => inner.IncrementCreateGistCount(); + public void IncrementLaunchCount() => inner.IncrementLaunchCount(); + public void IncrementLinkToGitHubCount() => inner.IncrementLinkToGitHubCount(); + public void IncrementLoginCount() => inner.IncrementLoginCount(); + public void IncrementOpenInGitHubCount() => inner.IncrementOpenInGitHubCount(); + public void IncrementPublishCount() => inner.IncrementPublishCount(); + public void IncrementUpstreamPullRequestCount() => inner.IncrementUpstreamPullRequestCount(); + } +} From ae92a2ca2514a37e47b1b4286cf866fb1e46708e Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 8 Nov 2016 11:48:45 +0100 Subject: [PATCH 2/3] Don't need to await getting the `IUsageTracker`. --- src/GitHub.VisualStudio/GitHubPackage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitHub.VisualStudio/GitHubPackage.cs b/src/GitHub.VisualStudio/GitHubPackage.cs index 48cf2a3e58..961a52cf9c 100644 --- a/src/GitHub.VisualStudio/GitHubPackage.cs +++ b/src/GitHub.VisualStudio/GitHubPackage.cs @@ -53,7 +53,7 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke await EnsurePackageLoaded(new Guid(ServiceProviderPackage.ServiceProviderPackageId)); // Activate the usage tracker by forcing an instance to be created. - await GetServiceAsync(typeof(IUsageTracker)); + GetServiceAsync(typeof(IUsageTracker)).Forget(); InitializeMenus().Forget(); } From c493e1e3f17d3977ea722d88088ce1961b842bc7 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 8 Nov 2016 12:39:00 +0100 Subject: [PATCH 3/3] Ensure UsageTracker services retreived on UI thread. Required changing most of the UsageTracker methods to be async. --- src/GitHub.App/Models/RepositoryHost.cs | 3 +- src/GitHub.App/Services/PullRequestService.cs | 2 +- .../ViewModels/GistCreationViewModel.cs | 2 +- .../ViewModels/RepositoryCloneViewModel.cs | 2 +- .../ViewModels/RepositoryCreationViewModel.cs | 2 +- .../ViewModels/RepositoryPublishViewModel.cs | 2 +- .../ViewModels/StartPageCloneViewModel.cs | 2 +- src/GitHub.Exports/Services/IUsageTracker.cs | 19 +++--- src/GitHub.VisualStudio/Menus/CopyLink.cs | 2 +- src/GitHub.VisualStudio/Menus/OpenLink.cs | 2 +- .../Services/UsageTracker.cs | 64 +++++++++---------- .../Services/UsageTrackerDispatcher.cs | 19 +++--- .../RepositoryCloneViewModelTests.cs | 3 +- 13 files changed, 62 insertions(+), 62 deletions(-) diff --git a/src/GitHub.App/Models/RepositoryHost.cs b/src/GitHub.App/Models/RepositoryHost.cs index bea24afa2c..4367e0f8c1 100644 --- a/src/GitHub.App/Models/RepositoryHost.cs +++ b/src/GitHub.App/Models/RepositoryHost.cs @@ -17,6 +17,7 @@ using System.Linq; using System.Reactive.Threading.Tasks; using System.Collections.Generic; +using GitHub.Extensions; namespace GitHub.Models { @@ -241,7 +242,7 @@ IObservable LoginWithApiUser(UserAndScopes userAndScopes) if (result.IsSuccess()) { var accountCacheItem = new AccountCacheItem(userAndScopes.User); - usage.IncrementLoginCount(); + usage.IncrementLoginCount().Forget(); return ModelService.InsertUser(accountCacheItem).Select(_ => result); } diff --git a/src/GitHub.App/Services/PullRequestService.cs b/src/GitHub.App/Services/PullRequestService.cs index f90fcd251c..6fefc8d4e0 100644 --- a/src/GitHub.App/Services/PullRequestService.cs +++ b/src/GitHub.App/Services/PullRequestService.cs @@ -91,7 +91,7 @@ async Task PushAndCreatePR(IRepositoryHost host, await Task.Delay(TimeSpan.FromSeconds(5)); var ret = await host.ModelService.CreatePullRequest(sourceRepository, targetRepository, sourceBranch, targetBranch, title, body); - usageTracker.IncrementUpstreamPullRequestCount(); + await usageTracker.IncrementUpstreamPullRequestCount(); return ret; } diff --git a/src/GitHub.App/ViewModels/GistCreationViewModel.cs b/src/GitHub.App/ViewModels/GistCreationViewModel.cs index d0974ad98c..203407ee7e 100644 --- a/src/GitHub.App/ViewModels/GistCreationViewModel.cs +++ b/src/GitHub.App/ViewModels/GistCreationViewModel.cs @@ -78,7 +78,7 @@ IObservable OnCreateGist(object unused) newGist.Files.Add(FileName, SelectedText); return gistPublishService.PublishGist(apiClient, newGist) - .Do(_ => usageTracker.IncrementCreateGistCount()) + .Do(_ => usageTracker.IncrementCreateGistCount().Forget()) .Catch(ex => { if (!ex.IsCriticalException()) diff --git a/src/GitHub.App/ViewModels/RepositoryCloneViewModel.cs b/src/GitHub.App/ViewModels/RepositoryCloneViewModel.cs index 27e2bd7926..1a608e0b3b 100644 --- a/src/GitHub.App/ViewModels/RepositoryCloneViewModel.cs +++ b/src/GitHub.App/ViewModels/RepositoryCloneViewModel.cs @@ -199,7 +199,7 @@ IObservable OnCloneRepository(object state) return cloneService.CloneRepository(repository.CloneUrl, repository.Name, BaseRepositoryPath) .ContinueAfter(() => { - usageTracker.IncrementCloneCount(); + usageTracker.IncrementCloneCount().Forget(); return Observable.Return(Unit.Default); }); }) diff --git a/src/GitHub.App/ViewModels/RepositoryCreationViewModel.cs b/src/GitHub.App/ViewModels/RepositoryCreationViewModel.cs index bf7623581c..2691490a29 100644 --- a/src/GitHub.App/ViewModels/RepositoryCreationViewModel.cs +++ b/src/GitHub.App/ViewModels/RepositoryCreationViewModel.cs @@ -268,7 +268,7 @@ IObservable OnCreateRepository(object state) SelectedAccount, BaseRepositoryPath, repositoryHost.ApiClient) - .Do(_ => usageTracker.IncrementCreateCount()); + .Do(_ => usageTracker.IncrementCreateCount().Forget()); } ReactiveCommand InitializeCreateRepositoryCommand() diff --git a/src/GitHub.App/ViewModels/RepositoryPublishViewModel.cs b/src/GitHub.App/ViewModels/RepositoryPublishViewModel.cs index 5f818c9d52..16b00d4c07 100644 --- a/src/GitHub.App/ViewModels/RepositoryPublishViewModel.cs +++ b/src/GitHub.App/ViewModels/RepositoryPublishViewModel.cs @@ -153,7 +153,7 @@ IObservable OnPublishRepository(object arg) var account = SelectedAccount; return repositoryPublishService.PublishRepository(newRepository, account, SelectedHost.ApiClient) - .Do(_ => usageTracker.IncrementPublishCount()) + .Do(_ => usageTracker.IncrementPublishCount().Forget()) .Select(_ => ProgressState.Success) .Catch(ex => { diff --git a/src/GitHub.App/ViewModels/StartPageCloneViewModel.cs b/src/GitHub.App/ViewModels/StartPageCloneViewModel.cs index 15baf45480..05527c1d20 100644 --- a/src/GitHub.App/ViewModels/StartPageCloneViewModel.cs +++ b/src/GitHub.App/ViewModels/StartPageCloneViewModel.cs @@ -105,7 +105,7 @@ IObservable OnCloneRepository(object state) return cloneService.CloneRepository(repository.CloneUrl, repository.Name, BaseRepositoryPath) .ContinueAfter(() => { - usageTracker.IncrementCloneCount(); + usageTracker.IncrementCloneCount().Forget(); return Observable.Return(Unit.Default); }); }) diff --git a/src/GitHub.Exports/Services/IUsageTracker.cs b/src/GitHub.Exports/Services/IUsageTracker.cs index 4b43cdb202..08afb257dc 100644 --- a/src/GitHub.Exports/Services/IUsageTracker.cs +++ b/src/GitHub.Exports/Services/IUsageTracker.cs @@ -1,19 +1,20 @@ using GitHub.VisualStudio; using System.Runtime.InteropServices; +using System.Threading.Tasks; namespace GitHub.Services { [Guid(Guids.UsageTrackerId)] public interface IUsageTracker { - void IncrementLaunchCount(); - void IncrementCloneCount(); - void IncrementCreateCount(); - void IncrementPublishCount(); - void IncrementOpenInGitHubCount(); - void IncrementLinkToGitHubCount(); - void IncrementCreateGistCount(); - void IncrementUpstreamPullRequestCount(); - void IncrementLoginCount(); + Task IncrementLaunchCount(); + Task IncrementCloneCount(); + Task IncrementCreateCount(); + Task IncrementPublishCount(); + Task IncrementOpenInGitHubCount(); + Task IncrementLinkToGitHubCount(); + Task IncrementCreateGistCount(); + Task IncrementUpstreamPullRequestCount(); + Task IncrementLoginCount(); } } diff --git a/src/GitHub.VisualStudio/Menus/CopyLink.cs b/src/GitHub.VisualStudio/Menus/CopyLink.cs index 889906000a..b1f30af91f 100644 --- a/src/GitHub.VisualStudio/Menus/CopyLink.cs +++ b/src/GitHub.VisualStudio/Menus/CopyLink.cs @@ -31,7 +31,7 @@ public async void Activate([AllowNull]object data = null) Clipboard.SetText(link); var ns = ServiceProvider.TryGetService(); ns?.ShowMessage(Resources.LinkCopiedToClipboardMessage); - UsageTracker.IncrementLinkToGitHubCount(); + await UsageTracker.IncrementLinkToGitHubCount(); } catch { diff --git a/src/GitHub.VisualStudio/Menus/OpenLink.cs b/src/GitHub.VisualStudio/Menus/OpenLink.cs index dac26b948d..b0e9bd7ab6 100644 --- a/src/GitHub.VisualStudio/Menus/OpenLink.cs +++ b/src/GitHub.VisualStudio/Menus/OpenLink.cs @@ -26,7 +26,7 @@ public async void Activate([AllowNull]object data = null) var browser = ServiceProvider.TryGetService(); browser?.OpenUrl(link.ToUri()); - UsageTracker.IncrementOpenInGitHubCount(); + await UsageTracker.IncrementOpenInGitHubCount(); } public bool CanShow() diff --git a/src/GitHub.VisualStudio/Services/UsageTracker.cs b/src/GitHub.VisualStudio/Services/UsageTracker.cs index 9e066e6347..9f0caff5a9 100644 --- a/src/GitHub.VisualStudio/Services/UsageTracker.cs +++ b/src/GitHub.VisualStudio/Services/UsageTracker.cs @@ -11,6 +11,7 @@ using Microsoft.VisualStudio.Shell; using Task = System.Threading.Tasks.Task; using GitHub.Extensions; +using System.Threading.Tasks; namespace GitHub.Services { @@ -70,77 +71,79 @@ public UsageTracker(IUIProvider uiProvider) RunTimer(); } - public void IncrementLaunchCount() + public async Task IncrementLaunchCount() { - var usage = LoadUsage(); + var usage = await LoadUsage(); ++usage.Model.NumberOfStartups; ++usage.Model.NumberOfStartupsWeek; ++usage.Model.NumberOfStartupsMonth; SaveUsage(usage); } - public void IncrementCloneCount() + public async Task IncrementCloneCount() { - var usage = LoadUsage(); + var usage = await LoadUsage(); ++usage.Model.NumberOfClones; SaveUsage(usage); } - public void IncrementCreateCount() + public async Task IncrementCreateCount() { - var usage = LoadUsage(); + var usage = await LoadUsage(); ++usage.Model.NumberOfReposCreated; SaveUsage(usage); } - public void IncrementPublishCount() + public async Task IncrementPublishCount() { - var usage = LoadUsage(); + var usage = await LoadUsage(); ++usage.Model.NumberOfReposPublished; SaveUsage(usage); } - public void IncrementOpenInGitHubCount() + public async Task IncrementOpenInGitHubCount() { - var usage = LoadUsage(); + var usage = await LoadUsage(); ++usage.Model.NumberOfOpenInGitHub; SaveUsage(usage); } - public void IncrementLinkToGitHubCount() + public async Task IncrementLinkToGitHubCount() { - var usage = LoadUsage(); + var usage = await LoadUsage(); ++usage.Model.NumberOfLinkToGitHub; SaveUsage(usage); } - public void IncrementCreateGistCount() + public async Task IncrementCreateGistCount() { - var usage = LoadUsage(); + var usage = await LoadUsage(); ++usage.Model.NumberOfGists; SaveUsage(usage); } - public void IncrementUpstreamPullRequestCount() + public async Task IncrementUpstreamPullRequestCount() { - var usage = LoadUsage(); + var usage = await LoadUsage(); ++usage.Model.NumberOfUpstreamPullRequests; SaveUsage(usage); } - public void IncrementLoginCount() + public async Task IncrementLoginCount() { - var usage = LoadUsage(); + var usage = await LoadUsage(); ++usage.Model.NumberOfLogins; SaveUsage(usage); } - void Initialize() + async Task Initialize() { // The services needed by the usage tracker are loaded when they are first needed to // improve the startup time of the extension. if (userSettings == null) { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + client = uiProvider.GetService(); connectionManager = uiProvider.GetService(); userSettings = uiProvider.GetService(); @@ -154,9 +157,9 @@ void Initialize() } } - UsageStore LoadUsage() + async Task LoadUsage() { - Initialize(); + await Initialize(); var json = fileExists(storePath) ? readAllText(storePath, Encoding.UTF8) : null; UsageStore result = null; @@ -204,33 +207,26 @@ void TimerTick(object sender, EventArgs e) async Task TimerTick() { - Initialize(); + await Initialize(); if (firstRun) { - IncrementLaunchCount(); + await IncrementLaunchCount(); timer.Interval = TimeSpan.FromHours(8); firstRun = false; } - if (userSettings == null) + if (client == null || !userSettings.CollectMetrics) { - await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); - if (client == null) - { - timer.Stop(); - return; - } - } - - if (!userSettings.CollectMetrics) + timer.Stop(); return; + } // Every time we increment the launch count we increment both daily and weekly // launch count but we only submit (and clear) the weekly launch count when we've // transitioned into a new week. We've defined a week by the ISO8601 definition, // i.e. week starting on Monday and ending on Sunday. - var usage = LoadUsage(); + var usage = await LoadUsage(); var lastDate = usage.LastUpdated; var currentDate = DateTimeOffset.Now; var includeWeekly = GetIso8601WeekOfYear(lastDate) != GetIso8601WeekOfYear(currentDate); diff --git a/src/GitHub.VisualStudio/Services/UsageTrackerDispatcher.cs b/src/GitHub.VisualStudio/Services/UsageTrackerDispatcher.cs index b58d68de33..854eb74e76 100644 --- a/src/GitHub.VisualStudio/Services/UsageTrackerDispatcher.cs +++ b/src/GitHub.VisualStudio/Services/UsageTrackerDispatcher.cs @@ -1,6 +1,7 @@ using Microsoft.VisualStudio.Shell; using System; using System.ComponentModel.Composition; +using Task = System.Threading.Tasks.Task; namespace GitHub.Services { @@ -16,14 +17,14 @@ public UsageTrackerDispatcher([Import(typeof(SVsServiceProvider))] IServiceProvi inner = serviceProvider.GetService(typeof(IUsageTracker)) as IUsageTracker; } - public void IncrementCloneCount() => inner.IncrementCloneCount(); - public void IncrementCreateCount() => inner.IncrementCreateCount(); - public void IncrementCreateGistCount() => inner.IncrementCreateGistCount(); - public void IncrementLaunchCount() => inner.IncrementLaunchCount(); - public void IncrementLinkToGitHubCount() => inner.IncrementLinkToGitHubCount(); - public void IncrementLoginCount() => inner.IncrementLoginCount(); - public void IncrementOpenInGitHubCount() => inner.IncrementOpenInGitHubCount(); - public void IncrementPublishCount() => inner.IncrementPublishCount(); - public void IncrementUpstreamPullRequestCount() => inner.IncrementUpstreamPullRequestCount(); + public Task IncrementCloneCount() => inner.IncrementCloneCount(); + public Task IncrementCreateCount() => inner.IncrementCreateCount(); + public Task IncrementCreateGistCount() => inner.IncrementCreateGistCount(); + public Task IncrementLaunchCount() => inner.IncrementLaunchCount(); + public Task IncrementLinkToGitHubCount() => inner.IncrementLinkToGitHubCount(); + public Task IncrementLoginCount() => inner.IncrementLoginCount(); + public Task IncrementOpenInGitHubCount() => inner.IncrementOpenInGitHubCount(); + public Task IncrementPublishCount() => inner.IncrementPublishCount(); + public Task IncrementUpstreamPullRequestCount() => inner.IncrementUpstreamPullRequestCount(); } } diff --git a/src/UnitTests/GitHub.App/ViewModels/RepositoryCloneViewModelTests.cs b/src/UnitTests/GitHub.App/ViewModels/RepositoryCloneViewModelTests.cs index 6186f3902f..ae990f16f3 100644 --- a/src/UnitTests/GitHub.App/ViewModels/RepositoryCloneViewModelTests.cs +++ b/src/UnitTests/GitHub.App/ViewModels/RepositoryCloneViewModelTests.cs @@ -13,6 +13,7 @@ using GitHub.Api; using Akavache; using GitHub.Collections; +using GitHub.Extensions; public class RepositoryCloneViewModelTests { @@ -358,7 +359,7 @@ public async Task UpdatesMetricsWhenRepositoryCloned() vm.SelectedRepository = Substitute.For(); await vm.CloneCommand.ExecuteAsync(); - usageTracker.Received().IncrementCloneCount(); + usageTracker.Received().IncrementCloneCount().Forget(); } } }