Show folder names immediately and refresh stale index sizes without walking the whole drive.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-26 11:21:20 +02:00
parent 6fc7506eb7
commit e2916aef9c
88 changed files with 5373 additions and 544 deletions

View File

@@ -20,6 +20,8 @@ public sealed class SourceManager
private long _refreshCacheTimestamp;
private static readonly TimeSpan RefreshCacheTtl = TimeSpan.FromSeconds(2);
public event EventHandler<Source>? PresenceChanged;
public SourceManager(
IIndexStore store,
IVolumeService volumes,
@@ -176,6 +178,7 @@ public sealed class SourceManager
&& (source.Kind.IsNetwork() || PathRules.IsUnc(source.LastRootPath))
&& _volumes.IsPathReachable(source.LastRootPath))
{
await BringOnlineAsync(source, cancellationToken).ConfigureAwait(false);
continue;
}
@@ -282,6 +285,77 @@ public sealed class SourceManager
return source;
}
public async Task<Source?> MarkReachableAsync(string path, CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(path) || LocationRoots.IsVirtual(path))
{
return null;
}
if (!_store.CanWrite)
{
if (_remote is null)
{
return await FindByPathAsync(path, cancellationToken).ConfigureAwait(false);
}
var current = await FindByPathAsync(path, cancellationToken).ConfigureAwait(false);
if (current is { Status: SourceStatus.Online or SourceStatus.Stale or SourceStatus.Scanning })
{
return current;
}
var updated = await _remote.MarkReachableAsync(path, cancellationToken).ConfigureAwait(false);
InvalidateRefreshCache();
var source = updated ?? await FindByPathAsync(path, cancellationToken).ConfigureAwait(false);
if (source is not null)
{
RaisePresence(source);
}
return source;
}
var found = await FindByPathAsync(path, cancellationToken).ConfigureAwait(false);
if (found is null)
{
return null;
}
await BringOnlineAsync(found, cancellationToken).ConfigureAwait(false);
return found;
}
public async Task ConfirmAccessedAsync(string path, CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(path) || LocationRoots.IsVirtual(path))
{
return;
}
var source = await FindByPathAsync(path, cancellationToken).ConfigureAwait(false);
if (source is null || source.Status != SourceStatus.Offline)
{
return;
}
if (_volumes.IsPathReachable(path))
{
await MarkReachableAsync(path, cancellationToken).ConfigureAwait(false);
return;
}
for (var attempt = 0; attempt < 4; attempt++)
{
await Task.Delay(500, cancellationToken).ConfigureAwait(false);
if (_volumes.IsPathReachable(path))
{
await MarkReachableAsync(path, cancellationToken).ConfigureAwait(false);
return;
}
}
}
public bool IsPresentInWindows(Source source)
{
var online = _volumes.EnumerateOnlineVolumes();
@@ -528,6 +602,42 @@ public sealed class SourceManager
public Task<Source?> GetAsync(long id, CancellationToken cancellationToken = default)
=> _store.Sources.GetAsync(id, cancellationToken);
private async Task BringOnlineAsync(Source source, CancellationToken cancellationToken)
{
if (source.Status == SourceStatus.Scanning
&& await _store.ScanJobs.HasActiveAsync(source.Id, cancellationToken).ConfigureAwait(false))
{
return;
}
if (source.Status is SourceStatus.Online or SourceStatus.Stale)
{
return;
}
var wasOffline = source.Status == SourceStatus.Offline;
source.Status = SourceStatus.Online;
source.LastSeenUtc = _clock.UtcNow;
source.LastError = null;
await TryIndexWrite(
() => _store.Sources.UpsertAsync(source, cancellationToken),
"mark source online",
source.Id).ConfigureAwait(false);
if (source.IsIndexed && wasOffline)
{
await TryIndexWrite(
() => _store.Entries.MarkSourceOnlinePresentAsync(source.Id, cancellationToken),
"mark online",
source.Id).ConfigureAwait(false);
}
InvalidateRefreshCache();
RaisePresence(source);
}
private void RaisePresence(Source source)
=> PresenceChanged?.Invoke(this, source);
private async Task<SourceStatus> ResolveReachableStatusAsync(Source source, CancellationToken cancellationToken)
{
if (source.Status == SourceStatus.Scanning