Skip to content

Commit 79da94c

Browse files
authored
Allow Git workspaces to be "held" so they aren't auto-deleted (#368)
1 parent 6c59832 commit 79da94c

File tree

5 files changed

+84
-24
lines changed

5 files changed

+84
-24
lines changed

UET/Redpoint.Reservation/DefaultReservationManager.cs

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,23 +130,27 @@ public Task<IReservation> ReserveAsync(string @namespace, params string[] parame
130130
throw new InvalidOperationException($"There are too many reservations for the stability ID '{id}'!");
131131
}
132132

133-
public async Task<IReservation> ReserveExactAsync(string name, CancellationToken cancellationToken)
133+
public async Task<IReservation> ReserveExactAsync(string name, CancellationToken cancellationToken, bool? hold = null)
134134
{
135135
return (await ReserveExactInternalAsync(
136136
name,
137137
false,
138-
cancellationToken).ConfigureAwait(false))!;
138+
cancellationToken,
139+
hold).ConfigureAwait(false))!;
139140
}
140141

141-
public Task<IReservation?> TryReserveExactAsync(string name)
142+
public Task<IReservation?> TryReserveExactAsync(string name, bool? hold = null)
142143
{
143144
return ReserveExactInternalAsync(
144145
name,
145146
true,
146-
CancellationToken.None);
147+
CancellationToken.None,
148+
hold);
147149
}
148150

149-
public IReservation? TryReserveExact(string targetName)
151+
public IReservation? TryReserveExact(
152+
string targetName,
153+
bool? hold = null)
150154
{
151155
if (_localReservations.TryAdd(targetName, true))
152156
{
@@ -163,6 +167,21 @@ public async Task<IReservation> ReserveExactAsync(string name, CancellationToken
163167
_logger.LogTrace($"Reservation target '{targetName}' has been acquired in this process.");
164168
File.WriteAllLines(Path.Combine(_metaPath, "desc." + targetName), new[] { targetName });
165169
File.WriteAllText(Path.Combine(_metaPath, "date." + targetName), DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture));
170+
if (hold.HasValue)
171+
{
172+
try
173+
{
174+
if (hold.Value)
175+
{
176+
File.WriteAllText(Path.Combine(_metaPath, "hold." + targetName), "hold");
177+
}
178+
else
179+
{
180+
File.Delete(Path.Combine(_metaPath, "hold." + targetName));
181+
}
182+
}
183+
catch { }
184+
}
166185
return new Reservation(
167186
handle,
168187
reservedPath,
@@ -188,7 +207,11 @@ public async Task<IReservation> ReserveExactAsync(string name, CancellationToken
188207
}
189208
}
190209

191-
private async Task<IReservation?> ReserveExactInternalAsync(string targetName, bool allowFailure, CancellationToken cancellationToken)
210+
private async Task<IReservation?> ReserveExactInternalAsync(
211+
string targetName,
212+
bool allowFailure,
213+
CancellationToken cancellationToken,
214+
bool? hold = null)
192215
{
193216
do
194217
{
@@ -207,6 +230,21 @@ public async Task<IReservation> ReserveExactAsync(string name, CancellationToken
207230
_logger.LogTrace($"Reservation target '{targetName}' has been acquired in this process.");
208231
File.WriteAllLines(Path.Combine(_metaPath, "desc." + targetName), new[] { targetName });
209232
File.WriteAllText(Path.Combine(_metaPath, "date." + targetName), DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture));
233+
if (hold.HasValue)
234+
{
235+
try
236+
{
237+
if (hold.Value)
238+
{
239+
File.WriteAllText(Path.Combine(_metaPath, "hold." + targetName), "hold");
240+
}
241+
else
242+
{
243+
File.Delete(Path.Combine(_metaPath, "hold." + targetName));
244+
}
245+
}
246+
catch { }
247+
}
210248
return new Reservation(
211249
handle,
212250
reservedPath,

UET/Redpoint.Reservation/IReservationManager.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,27 @@ public interface IReservationManager
3030
/// </summary>
3131
/// <param name="name">The ID to reserve.</param>
3232
/// <param name="cancellationToken"></param>
33+
/// <param name="hold">If set, sets or clears the 'hold' flag which indicates to other systems they should not automatically delete this directory under low disk space scenarios.</param>
3334
/// <returns>The reservation.</returns>
3435
/// <exception cref="OperationCanceledException">The task was cancelled before the reservation could be made.</exception>
35-
Task<IReservation> ReserveExactAsync(string name, CancellationToken cancellationToken);
36+
Task<IReservation> ReserveExactAsync(string name, CancellationToken cancellationToken, bool? hold = null);
3637

3738
/// <summary>
3839
/// Try to reserve exactly the directory with the <paramref name="name"/>. If the directory is already
3940
/// reserved, this returns null.
4041
/// </summary>
4142
/// <param name="name">The ID to reserve.</param>
43+
/// <param name="hold">If set, sets or clears the 'hold' flag which indicates to other systems they should not automatically delete this directory under low disk space scenarios.</param>
4244
/// <returns>The reservation if it was made.</returns>
43-
Task<IReservation?> TryReserveExactAsync(string name);
45+
Task<IReservation?> TryReserveExactAsync(string name, bool? hold = null);
4446

4547
/// <summary>
4648
/// Try to reserve exactly the directory with the <paramref name="name"/>. If the directory is already
4749
/// reserved, this returns null.
4850
/// </summary>
4951
/// <param name="name">The ID to reserve.</param>
52+
/// <param name="hold">If set, sets or clears the 'hold' flag which indicates to other systems they should not automatically delete this directory under low disk space scenarios.</param>
5053
/// <returns>The reservation if it was made.</returns>
51-
IReservation? TryReserveExact(string name);
54+
IReservation? TryReserveExact(string name, bool? hold = null);
5255
}
5356
}

UET/Redpoint.Uet.Workspace/DefaultWorkspaceProvider.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,20 @@ private async Task<IWorkspace> AllocateGitAsync(GitWorkspaceDescriptor descripto
154154
{
155155
_logger.LogInformation("Reserving exact workspace as this Git workspace descriptor has concurrent=false...");
156156

157+
bool? hold = null;
158+
if (descriptor.QueryString?["hold"] == "true")
159+
{
160+
hold = true;
161+
}
162+
else if (descriptor.QueryString?["hold"] == "false")
163+
{
164+
hold = false;
165+
}
166+
157167
reservation = await _reservationManager.ReserveExactAsync(
158-
StabilityHash.GetStabilityHash($"PhysicalGit:{string.Join("-", [repositoryUniqueUrl, descriptor.RepositoryBranchForReservationParameters])}", 14),
159-
cancellationToken).ConfigureAwait(false);
168+
StabilityHash.GetStabilityHash($"PhysicalGit:{string.Join("-", [repositoryUniqueUrl, descriptor.RepositoryBranchForReservationParameters])}", 14),
169+
cancellationToken,
170+
hold: hold).ConfigureAwait(false);
160171
}
161172
else
162173
{

UET/Redpoint.Uet.Workspace/Reservation/DefaultReservationManagerForUET.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,19 @@ public Task<IReservation> ReserveAsync(string @namespace, params string[] parame
2323
return _reservationManager.ReserveAsync(@namespace, parameters);
2424
}
2525

26-
public Task<IReservation> ReserveExactAsync(string name, CancellationToken cancellationToken)
26+
public Task<IReservation> ReserveExactAsync(string name, CancellationToken cancellationToken, bool? hold)
2727
{
28-
return _reservationManager.ReserveExactAsync(name, cancellationToken);
28+
return _reservationManager.ReserveExactAsync(name, cancellationToken, hold);
2929
}
3030

31-
public IReservation? TryReserveExact(string name)
31+
public IReservation? TryReserveExact(string name, bool? hold)
3232
{
33-
return _reservationManager.TryReserveExact(name);
33+
return _reservationManager.TryReserveExact(name, hold);
3434
}
3535

36-
public Task<IReservation?> TryReserveExactAsync(string name)
36+
public Task<IReservation?> TryReserveExactAsync(string name, bool? hold)
3737
{
38-
return _reservationManager.TryReserveExactAsync(name);
38+
return _reservationManager.TryReserveExactAsync(name, hold);
3939
}
4040
}
4141
}

UET/Redpoint.Uet.Workspace/Storage/DefaultStorageManagement.cs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public async Task<ListStorageResult> ListStorageAsync(
5252
Action<(int total, int remaining)> onProgress,
5353
CancellationToken cancellationToken)
5454
{
55-
var scan = new List<(DirectoryInfo dir, FileInfo? metaFile, StorageEntryType type)>();
55+
var scan = new List<(DirectoryInfo dir, FileInfo? metaFile, FileInfo? holdFile, StorageEntryType type)>();
5656
var reservationRoot = new DirectoryInfo(_reservationManagerRootPath);
5757
if (reservationRoot.Exists)
5858
{
@@ -61,6 +61,7 @@ public async Task<ListStorageResult> ListStorageAsync(
6161
.Select(x => (
6262
x,
6363
(FileInfo?)new FileInfo(Path.Combine(reservationRoot.FullName, ".meta", "date." + x.Name)),
64+
(FileInfo?)new FileInfo(Path.Combine(reservationRoot.FullName, ".meta", "hold." + x.Name)),
6465
StorageEntryType.Generic)));
6566
}
6667

@@ -69,11 +70,11 @@ public async Task<ListStorageResult> ListStorageAsync(
6970
{
7071
scan.AddRange(new[]
7172
{
72-
(new DirectoryInfo(Path.Combine(UetPaths.UefsRootPath, "git-blob")), (FileInfo?)null, StorageEntryType.UefsGitSharedBlobs),
73-
(new DirectoryInfo(Path.Combine(UetPaths.UefsRootPath, "git-deps")), null, StorageEntryType.UefsGitSharedDependencies),
74-
(new DirectoryInfo(Path.Combine(UetPaths.UefsRootPath, "git-index-cache")), null, StorageEntryType.UefsGitSharedIndexCache),
75-
(new DirectoryInfo(Path.Combine(UetPaths.UefsRootPath, "git-repo")), null, StorageEntryType.UefsGitSharedRepository),
76-
(new DirectoryInfo(Path.Combine(UetPaths.UefsRootPath, "hostpkgs", "cache")), null, StorageEntryType.UefsHostPackagesCache),
73+
(new DirectoryInfo(Path.Combine(UetPaths.UefsRootPath, "git-blob")), (FileInfo?)null, (FileInfo?)null, StorageEntryType.UefsGitSharedBlobs),
74+
(new DirectoryInfo(Path.Combine(UetPaths.UefsRootPath, "git-deps")), null, null, StorageEntryType.UefsGitSharedDependencies),
75+
(new DirectoryInfo(Path.Combine(UetPaths.UefsRootPath, "git-index-cache")), null, null, StorageEntryType.UefsGitSharedIndexCache),
76+
(new DirectoryInfo(Path.Combine(UetPaths.UefsRootPath, "git-repo")), null, null, StorageEntryType.UefsGitSharedRepository),
77+
(new DirectoryInfo(Path.Combine(UetPaths.UefsRootPath, "hostpkgs", "cache")), null, null, StorageEntryType.UefsHostPackagesCache),
7778
});
7879
}
7980

@@ -227,7 +228,7 @@ public async Task PurgeStorageAsync(
227228
int daysThreshold,
228229
CancellationToken cancellationToken)
229230
{
230-
var scan = new List<(DirectoryInfo dir, FileInfo? metaFile, StorageEntryType type)>();
231+
var scan = new List<(DirectoryInfo dir, FileInfo? metaFile, FileInfo? holdFile, StorageEntryType type)>();
231232
var reservationRoot = new DirectoryInfo(_reservationManagerRootPath);
232233
if (reservationRoot.Exists)
233234
{
@@ -236,6 +237,7 @@ public async Task PurgeStorageAsync(
236237
.Select(x => (
237238
x,
238239
(FileInfo?)new FileInfo(Path.Combine(reservationRoot.FullName, ".meta", "date." + x.Name)),
240+
(FileInfo?)new FileInfo(Path.Combine(reservationRoot.FullName, ".meta", "hold." + x.Name)),
239241
StorageEntryType.Generic)));
240242
}
241243
var remaining = scan.Count;
@@ -256,6 +258,12 @@ await Parallel.ForEachAsync(
256258
return;
257259
}
258260

261+
if (entry.holdFile?.Exists ?? false)
262+
{
263+
_logger.LogWarning($"Directory '{directory.FullName}' currently has a hold applied; refusing to remove.");
264+
return;
265+
}
266+
259267
var lastUsed = GetLastUsedFromMetaFile(directory, entry.metaFile);
260268

261269
var lastUsedDays = now - lastUsed;

0 commit comments

Comments
 (0)