Persist file categories on the index and classify archives and unknown types during idle maintenance.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-28 11:37:29 +02:00
parent b33a78dbbe
commit 222b5d9969
42 changed files with 1719 additions and 80 deletions

View File

@@ -149,6 +149,44 @@ public class BackgroundMaintenanceCoordinatorTests
Assert.Empty(indexing.IdleScans);
}
[Fact]
public async Task Idle_classifies_before_hashing()
{
var hash = new FakeHash { Pending = true };
var indexing = new FakeIndexing();
var classify = new FakeClassify { Work = true };
var coordinator = Create(hash, indexing, idle: TimeSpan.FromMinutes(20), classify: classify);
await coordinator.TickAsync(CancellationToken.None);
Assert.Equal(1, classify.Calls);
Assert.True(hash.IsPaused);
Assert.Contains("classifying", coordinator.Snapshot.Message, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public async Task Idle_hashes_when_classify_is_idle()
{
var hash = new FakeHash { Pending = true };
var indexing = new FakeIndexing();
var classify = new FakeClassify();
var coordinator = Create(hash, indexing, idle: TimeSpan.FromMinutes(20), classify: classify);
await coordinator.TickAsync(CancellationToken.None);
Assert.Equal(1, classify.Calls);
Assert.False(hash.IsPaused);
Assert.Contains("hashing", coordinator.Snapshot.Message, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public async Task Activity_pauses_classify()
{
var hash = new FakeHash();
var indexing = new FakeIndexing();
var classify = new FakeClassify { Paused = false };
var coordinator = Create(hash, indexing, idle: TimeSpan.Zero, classify: classify);
await coordinator.TickAsync(CancellationToken.None);
Assert.True(classify.IsPaused);
Assert.Equal(0, classify.Calls);
}
private static Source StaleLocal()
=> new()
{
@@ -168,8 +206,9 @@ public class BackgroundMaintenanceCoordinatorTests
bool enabled = true,
bool ac = true,
bool foreground = false,
IReadOnlyList<Source>? sources = null)
=> Create(hash, indexing, new FakeIdle(idle), enabled, ac, foreground, sources);
IReadOnlyList<Source>? sources = null,
FakeClassify? classify = null)
=> Create(hash, indexing, new FakeIdle(idle), enabled, ac, foreground, sources, classify);
private static BackgroundMaintenanceCoordinator Create(
FakeHash hash,
@@ -178,7 +217,8 @@ public class BackgroundMaintenanceCoordinatorTests
bool enabled = true,
bool ac = true,
bool foreground = false,
IReadOnlyList<Source>? sources = null)
IReadOnlyList<Source>? sources = null,
FakeClassify? classify = null)
{
var dir = Path.Combine(Path.GetTempPath(), "ew-maint", Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(dir);
@@ -199,7 +239,8 @@ public class BackgroundMaintenanceCoordinatorTests
new FakeHistory(),
new FakeStore(sources ?? []),
new FakeVolumes(),
NullLogger<BackgroundMaintenanceCoordinator>.Instance);
NullLogger<BackgroundMaintenanceCoordinator>.Instance,
classify: classify);
}
private sealed class FakeIdle(TimeSpan idle) : IUserIdleMonitor
@@ -233,14 +274,31 @@ public class BackgroundMaintenanceCoordinatorTests
private sealed class FakeHash : IIdleHashWork
{
public bool Pending { get; set; }
public bool Paused { get; set; } = true;
public bool IsPaused => Paused;
public string? CurrentPath => null;
public void Pause() => Paused = true;
public void Resume() => Paused = false;
public void BeginUserRequested() { }
public Task<bool> HasPendingAsync(CancellationToken cancellationToken = default) => Task.FromResult(false);
public Task<long> CountPendingAsync(CancellationToken cancellationToken = default) => Task.FromResult(0L);
public Task<bool> HasPendingAsync(CancellationToken cancellationToken = default) => Task.FromResult(Pending);
public Task<long> CountPendingAsync(CancellationToken cancellationToken = default) => Task.FromResult(Pending ? 1L : 0L);
}
private sealed class FakeClassify : IIdleClassifyWork
{
public bool Work { get; set; }
public int Calls { get; private set; }
public bool Paused { get; set; } = true;
public bool IsPaused => Paused;
public string? CurrentPath => null;
public void Pause() => Paused = true;
public void Resume() => Paused = false;
public Task<bool> ProcessPendingAsync(CancellationToken cancellationToken = default)
{
Calls++;
return Task.FromResult(Work);
}
}
private sealed class FakeHistory : IHistoryMaintenance

View File

@@ -36,6 +36,7 @@ public class CoreRegistrationTests
Assert.NotNull(sp.GetService<IBackgroundMaintenance>());
Assert.NotNull(sp.GetService<IUserIdleMonitor>());
Assert.NotNull(sp.GetService<IPowerSourceMonitor>());
Assert.NotNull(sp.GetService<IIdleClassifyWork>());
Assert.IsType<StorageProviderRegistry>(sp.GetService<ICloudOverlay>());
}
finally