Skip to content

Commit 21f5dcd

Browse files
committed
collect result releases into a diot before acquiring the semaphore to prevent deadlocks in the future
1 parent 8d73366 commit 21f5dcd

1 file changed

Lines changed: 44 additions & 23 deletions

File tree

src/Server/Services/GitLab/VersionCache.cs

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Gommon;
33
using NGitLab;
44
using NGitLab.Models;
5+
using NuGet.Packaging;
56
using Ryujinx.Systems.Update.Common;
67

78
namespace Ryujinx.Systems.Update.Server.Services.GitLab;
@@ -132,51 +133,71 @@ public async Task RefreshAsync()
132133

133134
if (releases is null)
134135
return;
135-
136-
await _semaphore.WaitAsync();
137-
138-
if (Count > 0)
139-
{
140-
_logger.LogInformation("Clearing {entryCount} version cache entries for {project}", Count,
141-
_cachedProject!.Value.Name);
142-
Clear();
143-
}
144136

145-
foreach (var release in releases)
146-
{
147-
_logger.LogTrace("Adding version cache entry {tag} for {project}", release.TagName, _cachedProject!.Value.Name);
148-
this[release.TagName] = new VersionCacheEntry
137+
var tempCacheEntries = releases.Select(release =>
138+
new VersionCacheEntry
149139
{
150140
Tag = release.TagName,
151141
ReleaseUrl = ReleaseUrlFormat.Format(release.TagName),
152142
Downloads =
153143
{
154144
Windows =
155145
{
156-
X64 = release.Assets.Links.FirstOrDefault(x => x.AssetName.ContainsIgnoreCase("win_x64"))?.Url ?? string.Empty,
157-
Arm64 = release.Assets.Links.FirstOrDefault(x => x.AssetName.ContainsIgnoreCase("win_arm64"))?.Url ?? string.Empty
146+
X64 = release.Assets.Links
147+
.FirstOrDefault(x => x.AssetName.ContainsIgnoreCase("win_x64"))
148+
?.Url ?? string.Empty,
149+
Arm64 = release.Assets.Links
150+
.FirstOrDefault(x => x.AssetName.ContainsIgnoreCase("win_arm64"))
151+
?.Url ?? string.Empty
158152
},
159153
Linux =
160154
{
161-
X64 = release.Assets.Links.FirstOrDefault(x => x.AssetName.ContainsIgnoreCase("linux_x64"))?.Url ?? string.Empty,
162-
Arm64 = release.Assets.Links.FirstOrDefault(x => x.AssetName.ContainsIgnoreCase("linux_arm64"))?.Url ?? string.Empty
155+
X64 = release.Assets.Links
156+
.FirstOrDefault(x => x.AssetName.ContainsIgnoreCase("linux_x64"))
157+
?.Url ?? string.Empty,
158+
Arm64 = release.Assets.Links
159+
.FirstOrDefault(x => x.AssetName.ContainsIgnoreCase("linux_arm64"))
160+
?.Url ?? string.Empty
163161
},
164162
LinuxAppImage =
165163
{
166-
X64 = release.Assets.Links.FirstOrDefault(x => x.AssetName.EndsWithIgnoreCase("x64.AppImage"))?.Url ?? string.Empty,
167-
Arm64 = release.Assets.Links.FirstOrDefault(x => x.AssetName.EndsWithIgnoreCase("arm64.AppImage"))?.Url ?? string.Empty
164+
X64 = release.Assets.Links
165+
.FirstOrDefault(x => x.AssetName.EndsWithIgnoreCase("x64.AppImage"))
166+
?.Url ?? string.Empty,
167+
Arm64 = release.Assets.Links
168+
.FirstOrDefault(x => x.AssetName.EndsWithIgnoreCase("arm64.AppImage"))
169+
?.Url ?? string.Empty
168170
},
169-
MacOS = release.Assets.Links.FirstOrDefault(x => x.AssetName.ContainsIgnoreCase("macos_universal"))?.Url ?? string.Empty
171+
MacOS = release.Assets.Links
172+
.FirstOrDefault(x => x.AssetName.ContainsIgnoreCase("macos_universal"))
173+
?.Url ?? string.Empty
170174
}
171-
};
175+
}).ToDictionary(x => x.Tag, x => x);
176+
177+
await _semaphore.WaitAsync();
178+
179+
if (Count > 0)
180+
{
181+
_logger.LogInformation("Clearing {entryCount} version cache entries for {project}", Count,
182+
_cachedProject!.Value.Name);
183+
Clear();
172184
}
173185

186+
foreach (var (tag, entry) in tempCacheEntries)
187+
{
188+
_logger.LogTrace("Adding version cache entry {tag} for {project}", tag, _cachedProject!.Value.Name);
189+
190+
this[tag] = entry;
191+
}
192+
193+
tempCacheEntries.Clear();
194+
174195
sw.Stop();
196+
197+
_semaphore.Release();
175198

176199
_logger.LogInformation("Loaded {entryCount} version cache entries for {project}; took {time}ms.", Count,
177200
_cachedProject!.Value.Name, sw.ElapsedMilliseconds);
178-
179-
_semaphore.Release();
180201
}
181202

182203
public static void InitializeVersionCaches(WebApplication app)

0 commit comments

Comments
 (0)