Skip to content
This repository was archived by the owner on Dec 5, 2024. It is now read-only.

Commit 389020d

Browse files
committed
Reduce the amount of invalidations the cache produces
Invalidating the cache is tricky - if it invalidates itself on first access and first access is the repository trying to set a value, updating the cache causes it to invalidate itself, which we don't want.
1 parent ecc06c0 commit 389020d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1695
-1392
lines changed

src/GitHub.Api/Application/ApplicationManagerBase.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,12 @@ public void Run(bool firstRun)
7373
{
7474
if (b && path != null)
7575
{
76-
Logger.Trace("FindExecTask Success: {0}", path);
76+
//Logger.Trace("FindExecTask Success: {0}", path);
7777
InitializeEnvironment(gitExecutablePath);
7878
}
7979
else
8080
{
81-
Logger.Warning("FindExecTask Failure");
81+
//Logger.Warning("FindExecTask Failure");
8282
Logger.Error("Git not found");
8383
}
8484
isBusy = false;
@@ -101,7 +101,7 @@ public void Run(bool firstRun)
101101

102102
public ITask InitializeRepository()
103103
{
104-
Logger.Trace("Running Repository Initialize");
104+
//Logger.Trace("Running Repository Initialize");
105105

106106
var targetPath = NPath.CurrentDirectory;
107107

@@ -146,18 +146,18 @@ public void RestartRepository()
146146
{
147147
if (Environment.RepositoryPath != null)
148148
{
149-
repositoryManager = Unity.RepositoryManager.CreateInstance(Platform, TaskManager, GitClient, ProcessManager, Environment.FileSystem, Environment.RepositoryPath);
149+
repositoryManager = Unity.RepositoryManager.CreateInstance(Platform, TaskManager, GitClient, Environment.FileSystem, Environment.RepositoryPath);
150150
repositoryManager.Initialize();
151-
Environment.Repository.Initialize(repositoryManager);
151+
Environment.Repository.Initialize(repositoryManager, TaskManager);
152152
repositoryManager.Start();
153153
Environment.Repository.Start();
154-
Logger.Trace($"Got a repository? {Environment.Repository}");
154+
Logger.Trace($"Got a repository? {(Environment.Repository != null ? Environment.Repository.LocalPath : "null")}");
155155
}
156156
}
157157

158158
protected void SetupMetrics(string unityVersion, bool firstRun)
159159
{
160-
Logger.Trace("Setup metrics");
160+
//Logger.Trace("Setup metrics");
161161

162162
var usagePath = Environment.UserCachePath.Combine(Constants.UsageFile);
163163

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using GitHub.Logging;
4+
5+
namespace GitHub.Unity
6+
{
7+
public class CacheContainer : ICacheContainer
8+
{
9+
private static ILogging Logger = LogHelper.GetLogger<CacheContainer>();
10+
11+
private Dictionary<CacheType, Lazy<IManagedCache>> caches = new Dictionary<CacheType, Lazy<IManagedCache>>();
12+
13+
public event Action<CacheType> CacheInvalidated;
14+
public event Action<CacheType, DateTimeOffset> CacheUpdated;
15+
16+
public void SetCacheInitializer(CacheType cacheType, Func<IManagedCache> initializer)
17+
{
18+
caches.Add(cacheType, new Lazy<IManagedCache>(() => SetupCache(initializer())));
19+
}
20+
21+
public void ValidateAll()
22+
{
23+
// this can trigger invalidation requests fyi
24+
foreach (var cache in caches.Values)
25+
cache.Value.ValidateData();
26+
}
27+
28+
public void InvalidateAll()
29+
{
30+
foreach (var cache in caches.Values)
31+
{
32+
// force an invalidation if the cache is valid, otherwise it will do it on its own
33+
if (cache.Value.ValidateData())
34+
cache.Value.InvalidateData();
35+
}
36+
}
37+
38+
private IManagedCache SetupCache(IManagedCache cache)
39+
{
40+
cache.CacheInvalidated += () => OnCacheInvalidated(cache.CacheType);
41+
cache.CacheUpdated += datetime => OnCacheUpdated(cache.CacheType, datetime);
42+
return cache;
43+
}
44+
45+
public IManagedCache GetCache(CacheType cacheType)
46+
{
47+
return caches[cacheType].Value;
48+
}
49+
50+
public void CheckAndRaiseEventsIfCacheNewer(CacheUpdateEvent cacheUpdateEvent)
51+
{
52+
var cache = GetCache(cacheUpdateEvent.cacheType);
53+
if (cache.LastUpdatedAt != cacheUpdateEvent.UpdatedTime)
54+
{
55+
OnCacheUpdated(cache.CacheType, cache.LastUpdatedAt);
56+
}
57+
}
58+
59+
private void OnCacheUpdated(CacheType cacheType, DateTimeOffset datetime)
60+
{
61+
Logger.Trace("OnCacheUpdated cacheType:{0} datetime:{1}", cacheType, datetime);
62+
CacheUpdated.SafeInvoke(cacheType, datetime);
63+
}
64+
65+
private void OnCacheInvalidated(CacheType cacheType)
66+
{
67+
Logger.Trace("OnCacheInvalidated cacheType:{0}", cacheType);
68+
CacheInvalidated.SafeInvoke(cacheType);
69+
}
70+
71+
public IBranchCache BranchCache { get { return (IBranchCache)caches[CacheType.Branches].Value; } }
72+
public IGitLogCache GitLogCache { get { return (IGitLogCache)caches[CacheType.GitLog].Value; } }
73+
public IGitAheadBehindCache GitTrackingStatusCache { get { return (IGitAheadBehindCache)caches[CacheType.GitAheadBehind].Value; } }
74+
public IGitStatusCache GitStatusEntriesCache { get { return (IGitStatusCache)caches[CacheType.GitStatus].Value; } }
75+
public IGitLocksCache GitLocksCache { get { return (IGitLocksCache)caches[CacheType.GitLocks].Value; } }
76+
public IGitUserCache GitUserCache { get { return (IGitUserCache)caches[CacheType.GitUser].Value; } }
77+
public IRepositoryInfoCache RepositoryInfoCache { get { return (IRepositoryInfoCache)caches[CacheType.RepositoryInfo].Value; } }
78+
}
79+
}

src/GitHub.Api/Cache/CacheInterfaces.cs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,27 @@ public interface ICacheContainer
2121

2222
IBranchCache BranchCache { get; }
2323
IGitLogCache GitLogCache { get; }
24-
IGitTrackingStatusCache GitTrackingStatusCache { get; }
25-
IGitStatusEntriesCache GitStatusEntriesCache { get; }
24+
IGitAheadBehindCache GitTrackingStatusCache { get; }
25+
IGitStatusCache GitStatusEntriesCache { get; }
2626
IGitLocksCache GitLocksCache { get; }
2727
IGitUserCache GitUserCache { get; }
2828
IRepositoryInfoCache RepositoryInfoCache { get; }
29-
void Validate(CacheType cacheType);
3029
void ValidateAll();
31-
void Invalidate(CacheType cacheType);
3230
void InvalidateAll();
31+
IManagedCache GetCache(CacheType cacheType);
32+
void CheckAndRaiseEventsIfCacheNewer(CacheUpdateEvent cacheUpdateEvent);
3333
}
3434

3535
public interface IManagedCache
3636
{
3737
event Action CacheInvalidated;
3838
event Action<DateTimeOffset> CacheUpdated;
3939

40-
void ValidateData();
40+
bool ValidateData();
4141
void InvalidateData();
4242

4343
DateTimeOffset LastUpdatedAt { get; }
44-
DateTimeOffset LastVerifiedAt { get; }
44+
CacheType CacheType { get; }
4545
}
4646

4747
public interface IGitLocksCache : IManagedCache
@@ -55,13 +55,13 @@ public interface IGitUserCache : IManagedCache
5555
string Email { get; set; }
5656
}
5757

58-
public interface IGitTrackingStatusCache : IManagedCache
58+
public interface IGitAheadBehindCache : IManagedCache
5959
{
6060
int Ahead { get; set; }
6161
int Behind { get; set; }
6262
}
6363

64-
public interface IGitStatusEntriesCache : IManagedCache
64+
public interface IGitStatusCache : IManagedCache
6565
{
6666
List<GitStatusEntry> Entries { get; set; }
6767
}
@@ -83,9 +83,6 @@ public interface IConfigRemoteDictionary : IDictionary<string, ConfigRemote>
8383

8484
public interface IBranchCache : IManagedCache
8585
{
86-
ConfigRemote? CurrentConfigRemote { get; set; }
87-
ConfigBranch? CurrentConfigBranch { get; set; }
88-
8986
GitBranch[] LocalBranches { get; set; }
9087
GitBranch[] RemoteBranches { get; set; }
9188
GitRemote[] Remotes { get; set; }
@@ -102,14 +99,21 @@ public interface IBranchCache : IManagedCache
10299
void SetLocals(Dictionary<string, ConfigBranch> branchDictionary);
103100
}
104101

105-
public interface IRepositoryInfoCache : IManagedCache
102+
public interface IRepositoryInfoCache : IManagedCache, ICanUpdate<IRepositoryInfoCache>
106103
{
107-
GitRemote? CurrentGitRemote { get; set; }
108-
GitBranch? CurrentGitBranch { get; set; }
104+
GitRemote? CurrentGitRemote { get; }
105+
GitBranch? CurrentGitBranch { get; }
106+
ConfigRemote? CurrentConfigRemote { get; }
107+
ConfigBranch? CurrentConfigBranch { get; }
109108
}
110109

111110
public interface IGitLogCache : IManagedCache
112111
{
113112
List<GitLogEntry> Log { get; set; }
114113
}
114+
115+
public interface ICanUpdate<T>
116+
{
117+
void UpdateData(T data);
118+
}
115119
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using GitHub.Logging;
2+
using GitHub.Unity;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Globalization;
6+
using System.Linq;
7+
using System.Runtime.Serialization;
8+
9+
namespace GitHub.Unity
10+
{
11+
class DataCache : IManagedCache
12+
{
13+
public DataCache(CacheType cacheType)
14+
{
15+
CacheType = cacheType;
16+
}
17+
public CacheType CacheType { get; }
18+
19+
public DateTimeOffset LastUpdatedAt { get; }
20+
21+
public event Action CacheInvalidated;
22+
public event Action<DateTimeOffset> CacheUpdated;
23+
24+
public void InvalidateData()
25+
{
26+
}
27+
28+
public bool ValidateData() => true;
29+
}
30+
31+
sealed class DataCache_RepositoryInfo : DataCache, IRepositoryInfoCache
32+
{
33+
public DataCache_RepositoryInfo() : base(CacheType.RepositoryInfo)
34+
{ }
35+
36+
public void UpdateData(IRepositoryInfoCache data)
37+
{
38+
}
39+
40+
public GitRemote? CurrentGitRemote { get; set; }
41+
public GitBranch? CurrentGitBranch { get; set; }
42+
43+
public ConfigRemote? CurrentConfigRemote { get; set; }
44+
45+
public ConfigBranch? CurrentConfigBranch { get; set; }
46+
47+
public TimeSpan DataTimeout { get { return TimeSpan.FromDays(1); } }
48+
}
49+
}

src/GitHub.Api/Events/RepositoryWatcher.cs

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -90,19 +90,19 @@ public void Stop()
9090
{
9191
if (!running)
9292
{
93-
Logger.Warning("Watcher already stopped");
93+
//Logger.Warning("Watcher already stopped");
9494
return;
9595
}
9696

97-
Logger.Trace("Stopping watcher");
97+
//Logger.Trace("Stopping watcher");
9898

9999
running = false;
100100
pauseEvent.Set();
101101
}
102102

103103
private void WatcherLoop()
104104
{
105-
Logger.Trace("Starting watcher");
105+
//Logger.Trace("Starting watcher");
106106

107107
while (running)
108108
{
@@ -136,9 +136,9 @@ public int CheckAndProcessEvents()
136136
var fileEvents = nativeInterface.GetEvents();
137137
if (fileEvents.Length > 0)
138138
{
139-
Logger.Trace("Handling {0} Events", fileEvents.Length);
139+
//Logger.Trace("Handling {0} Events", fileEvents.Length);
140140
processedEventCount = ProcessEvents(fileEvents);
141-
Logger.Trace("Processed {0} Events", processedEventCount);
141+
//Logger.Trace("Processed {0} Events", processedEventCount);
142142
}
143143

144144
lastCountOfProcessedEvents = processedEventCount;
@@ -215,49 +215,52 @@ private int FireEvents(HashSet<EventType> events)
215215
int eventsProcessed = 0;
216216
if (events.Contains(EventType.ConfigChanged))
217217
{
218-
Logger.Trace("ConfigChanged");
218+
//Logger.Trace("ConfigChanged");
219219
ConfigChanged?.Invoke();
220220
eventsProcessed++;
221221
}
222222

223223
if (events.Contains(EventType.HeadChanged))
224224
{
225-
Logger.Trace("HeadChanged");
225+
//Logger.Trace("HeadChanged");
226226
HeadChanged?.Invoke();
227227
eventsProcessed++;
228228
}
229229

230230
if (events.Contains(EventType.LocalBranchesChanged))
231231
{
232-
Logger.Trace("LocalBranchesChanged");
232+
//Logger.Trace("LocalBranchesChanged");
233233
LocalBranchesChanged?.Invoke();
234234
eventsProcessed++;
235235
}
236236

237237
if (events.Contains(EventType.RemoteBranchesChanged))
238238
{
239-
Logger.Trace("RemoteBranchesChanged");
239+
//Logger.Trace("RemoteBranchesChanged");
240240
RemoteBranchesChanged?.Invoke();
241241
eventsProcessed++;
242242
}
243243

244244
if (events.Contains(EventType.IndexChanged))
245245
{
246-
Logger.Trace("IndexChanged");
247-
IndexChanged?.Invoke();
248-
eventsProcessed++;
246+
if (!events.Contains(EventType.RepositoryChanged))
247+
{
248+
//Logger.Trace("IndexChanged");
249+
IndexChanged?.Invoke();
250+
eventsProcessed++;
251+
}
249252
}
250253

251254
if (events.Contains(EventType.RepositoryChanged))
252255
{
253-
Logger.Trace("RepositoryChanged");
256+
//Logger.Trace("RepositoryChanged");
254257
RepositoryChanged?.Invoke();
255258
eventsProcessed++;
256259
}
257260

258261
if (events.Contains(EventType.RepositoryCommitted))
259262
{
260-
Logger.Trace("RepositoryCommitted");
263+
//Logger.Trace("RepositoryCommitted");
261264
RepositoryCommitted?.Invoke();
262265
eventsProcessed++;
263266
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,11 @@ public static void SafeInvoke<T>(this Action<T> action, T obj)
1515
if (action != null)
1616
action(obj);
1717
}
18+
19+
public static void SafeInvoke<T1, T2>(this Action<T1, T2> action, T1 obj, T2 obj2)
20+
{
21+
if (action != null)
22+
action(obj, obj2);
23+
}
1824
}
1925
}

0 commit comments

Comments
 (0)