namespace Explorer.Domain.Abstractions; public interface IIndexStore { Task OpenAsync(CancellationToken cancellationToken = default); Task CloseAsync(); Task QuickCheckAsync(CancellationToken cancellationToken = default); ISourceStore Sources { get; } IEntryStore Entries { get; } IExcludeStore Excludes { get; } IScanJobStore ScanJobs { get; } ITransferStore Transfers { get; } ISearchStore Search { get; } IAnalysisStore Analysis { get; } IHistoryStore History { get; } IHashStore Hashes { get; } IFileRelationStore Relations { get; } IRenameBatchStore RenameBatches { get; } ISyncProfileStore SyncProfiles { get; } IOperationProfileStore OperationProfiles { get; } bool CanWrite { get; } Task RunWriteAsync(Func work, CancellationToken cancellationToken = default); Task RunWriteAsync(Func> work, CancellationToken cancellationToken = default); } public interface ISourceStore { Task> GetAllAsync(CancellationToken cancellationToken = default); Task GetAsync(long id, CancellationToken cancellationToken = default); Task GetByStableKeyAsync(string key, CancellationToken cancellationToken = default); Task UpsertAsync(Source source, CancellationToken cancellationToken = default); Task UpdateStatusAsync(long id, SourceStatus status, string? error, CancellationToken cancellationToken = default); Task UpdateUsnAsync(long id, long journalId, long nextUsn, CancellationToken cancellationToken = default); Task UpdateIndexedAsync(long id, DateTimeOffset utc, long generation, CancellationToken cancellationToken = default); Task SetLastSeenAsync(long id, string rootPath, DateTimeOffset utc, CancellationToken cancellationToken = default); Task DeleteAsync(long id, CancellationToken cancellationToken = default); } public interface IEntryStore { Task GetAsync(long id, CancellationToken cancellationToken = default); Task GetRootAsync(long sourceId, CancellationToken cancellationToken = default); Task GetByPathAsync(long sourceId, string pathRel, CancellationToken cancellationToken = default); Task GetByParentNameAsync(long sourceId, long? parentId, string nameNorm, CancellationToken cancellationToken = default); Task GetByFileIdAsync(long sourceId, long fileId, CancellationToken cancellationToken = default); Task> GetChildrenAsync(long sourceId, long? parentId, EntryStatus? status = EntryStatus.Present, CancellationToken cancellationToken = default); Task UpsertBatchAsync(IReadOnlyList entries, CancellationToken cancellationToken = default); Task UpsertAsync(IndexEntry entry, CancellationToken cancellationToken = default); Task UpdateAggregatesAsync(long id, long aggregateSize, int files, int dirs, CancellationToken cancellationToken = default); Task ApplySizeDeltaToAncestorsAsync(long? parentId, long sizeDelta, int fileDelta, int dirDelta, CancellationToken cancellationToken = default); Task MarkMissingAsDeletedAsync(long sourceId, long generation, DateTimeOffset utc, string? pathRelPrefix, CancellationToken cancellationToken = default); Task MarkSourceOfflineAsync(long sourceId, CancellationToken cancellationToken = default); Task MarkSourceOnlinePresentAsync(long sourceId, CancellationToken cancellationToken = default); Task TombstoneAsync(long id, DateTimeOffset utc, CancellationToken cancellationToken = default); Task TombstoneByPathPrefixAsync(long sourceId, string pathRelPrefix, DateTimeOffset utc, CancellationToken cancellationToken = default); Task DeleteExpiredTombstonesAsync(DateTimeOffset cutoffUtc, CancellationToken cancellationToken = default); Task RenameSubtreePathAsync(long sourceId, string oldPathRel, string newPathRel, CancellationToken cancellationToken = default); Task CountPresentAsync(long sourceId, CancellationToken cancellationToken = default); Task RefreshCategoryFromChildrenAsync(long folderOrArchiveId, CancellationToken cancellationToken = default); Task SetUserCategoryAsync(long entryId, FileCategory category, string? reason = null, CancellationToken cancellationToken = default); Task BackfillCheapCategoriesAsync(int take, CancellationToken cancellationToken = default); Task> GetArchiveIdsNeedingContentClassifyAsync(int take, CancellationToken cancellationToken = default); Task> GetUnknownFilesForSignatureAsync(int take, CancellationToken cancellationToken = default); } public interface IExcludeStore { Task> GetAllAsync(CancellationToken cancellationToken = default); Task AddAsync(ExcludeRule rule, CancellationToken cancellationToken = default); Task RemoveAsync(long id, CancellationToken cancellationToken = default); Task EnsureDefaultsAsync(IReadOnlyList defaults, CancellationToken cancellationToken = default); } public interface IScanJobStore { Task InsertAsync(ScanJob job, CancellationToken cancellationToken = default); Task UpdateAsync(ScanJob job, CancellationToken cancellationToken = default); Task InterruptRunningAsync(CancellationToken cancellationToken = default); Task HasActiveAsync(long sourceId, CancellationToken cancellationToken = default); Task AddErrorAsync(ScanError error, CancellationToken cancellationToken = default); Task GetAsync(long id, CancellationToken cancellationToken = default); Task> GetRecentAsync(int take, CancellationToken cancellationToken = default); } public interface ITransferStore { Task InsertAsync(TransferJob job, CancellationToken cancellationToken = default); Task UpdateAsync(TransferJob job, CancellationToken cancellationToken = default); Task> GetIncompleteAsync(CancellationToken cancellationToken = default); Task> GetHistoryAsync(int take, CancellationToken cancellationToken = default); } public interface ISearchStore { Task> SearchAsync(SearchRequest request, CancellationToken cancellationToken = default); } public sealed class SearchRequest { public string? Name { get; init; } public string? Extension { get; init; } public bool? IsDirectory { get; init; } public long? MinSize { get; init; } public long? MaxSize { get; init; } public DateTimeOffset? CreatedAfter { get; init; } public DateTimeOffset? CreatedBefore { get; init; } public DateTimeOffset? ModifiedAfter { get; init; } public DateTimeOffset? ModifiedBefore { get; init; } public IReadOnlyList? SourceIds { get; init; } public string? PathRelPrefix { get; init; } public bool DirectChildrenOnly { get; init; } public bool IncludeOffline { get; init; } = true; public bool IncludeDeleted { get; init; } public FileCategory? Category { get; init; } public int Skip { get; init; } public int Take { get; init; } = 500; } public interface IAnalysisStore { Task EnsureReadyAsync(CancellationToken cancellationToken = default); Task GetIndexStampAsync(CancellationToken cancellationToken = default); Task> GetDirectoryRootsAsync(CancellationToken cancellationToken = default); Task> LargestDirectoriesAsync(long? sourceId, long? parentId, int take, CancellationToken cancellationToken = default); Task> LargestFilesAsync(long? sourceId, string? pathRelPrefix, int take, CancellationToken cancellationToken = default); Task> UsageByExtensionAsync(long? sourceId, string? pathRelPrefix, int take, CancellationToken cancellationToken = default); Task> UsageByCategoryAsync(long? sourceId, string? pathRelPrefix, int take, CancellationToken cancellationToken = default); Task> UsageBySourceAsync(CancellationToken cancellationToken = default); Task> ChildrenBySizeAsync(long parentId, int take, CancellationToken cancellationToken = default); } public sealed class ExtensionUsage { public required string Extension { get; init; } public long TotalSize { get; init; } public long FileCount { get; init; } } public sealed class CategoryUsage { public required string Category { get; init; } public long TotalSize { get; init; } public long FileCount { get; init; } } public sealed class SourceUsage { public long SourceId { get; init; } public required string DisplayName { get; init; } public long TotalSize { get; init; } public long FileCount { get; init; } public SourceStatus Status { get; init; } } public interface IHistoryStore { Task CaptureSourceSnapshotAsync(long sourceId, DateTimeOffset utc, CancellationToken cancellationToken = default); Task CaptureDirectorySnapshotsAsync(long sourceId, DateTimeOffset utc, long minSize, int topN, CancellationToken cancellationToken = default); Task> GetSourceHistoryAsync(long sourceId, CancellationToken cancellationToken = default); } public sealed class SourceSnapshot { public DateTimeOffset CapturedUtc { get; init; } public long TotalSize { get; init; } public long FileCount { get; init; } public long DirCount { get; init; } } public interface IHashStore { Task EnqueueSizeCollisionsAsync(long? sourceId, CancellationToken cancellationToken = default); Task HasPendingAsync(CancellationToken cancellationToken = default); Task CountPendingAsync(CancellationToken cancellationToken = default); Task> DequeueAsync(int take, CancellationToken cancellationToken = default); Task CompletePartialAsync(long entryId, byte[] hash, CancellationToken cancellationToken = default); Task CompleteFullAsync(long entryId, byte[] hash, CancellationToken cancellationToken = default); Task MarkUniquePartialAsync(long entryId, CancellationToken cancellationToken = default); Task MarkErrorAsync(long entryId, CancellationToken cancellationToken = default); Task MarkSkippedAsync(long entryId, CancellationToken cancellationToken = default); Task HasPartialCollisionAsync(long entryId, long sizeBytes, CancellationToken cancellationToken = default); Task> GetDuplicateGroupsAsync(long? sourceId, string? pathPrefix, int take, CancellationToken cancellationToken = default); Task> GetDuplicateHashesAsync(long? sourceId, string? pathPrefix, int take, CancellationToken cancellationToken = default); Task> GetDuplicateGroupsByHashesAsync( IReadOnlyList hashes, CancellationToken cancellationToken = default); } public interface IFileRelationStore { Task> GetAmongAsync(IReadOnlyList entryIds, CancellationToken cancellationToken = default); Task UpsertAsync(FileRelation relation, CancellationToken cancellationToken = default); Task DeleteAmongAsync(IReadOnlyList entryIds, IReadOnlyList kinds, CancellationToken cancellationToken = default); } public interface IRenameBatchStore { Task CreateAsync(IReadOnlyList items, CancellationToken cancellationToken = default); Task GetLatestUndoableAsync(CancellationToken cancellationToken = default); Task MarkUndoneAsync(long id, CancellationToken cancellationToken = default); } public interface ISyncProfileStore { Task> ListAsync(CancellationToken cancellationToken = default); Task GetAsync(long id, CancellationToken cancellationToken = default); Task UpsertAsync(SyncProfile profile, CancellationToken cancellationToken = default); Task DeleteAsync(long id, CancellationToken cancellationToken = default); } public interface IOperationProfileStore { Task> ListAsync(CancellationToken cancellationToken = default); Task GetAsync(long id, CancellationToken cancellationToken = default); Task UpsertAsync(OperationProfile profile, CancellationToken cancellationToken = default); Task DeleteAsync(long id, CancellationToken cancellationToken = default); } public sealed class HashWorkItem { public long EntryId { get; init; } public long SizeBytes { get; init; } public required string State { get; init; } public long SourceId { get; init; } public required string PathRel { get; init; } public string? RootPath { get; init; } public long? FileId { get; init; } public int Attributes { get; init; } public CloudAvailability? CloudAvailability { get; init; } } public sealed class DuplicateGroup { public long SizeBytes { get; init; } public byte[]? Hash { get; init; } public IReadOnlyList Entries { get; init; } = []; public bool SameFileId { get; init; } }