Multi-Platform Package Manager for Stable Diffusion
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
4.6 KiB

using System.Diagnostics;
using Microsoft.Extensions.Logging;
using StabilityMatrix.Core.Database;
using StabilityMatrix.Core.Models;
using StabilityMatrix.Core.Models.Database;
using StabilityMatrix.Core.Models.FileInterfaces;
namespace StabilityMatrix.Core.Services;
public class ModelIndexService : IModelIndexService
{
private readonly ILogger<ModelIndexService> logger;
private readonly ILiteDbContext liteDbContext;
private readonly ISettingsManager settingsManager;
public ModelIndexService(
ILogger<ModelIndexService> logger,
ILiteDbContext liteDbContext,
ISettingsManager settingsManager
)
{
this.logger = logger;
this.liteDbContext = liteDbContext;
this.settingsManager = settingsManager;
}
/// <summary>
/// Deletes all entries in the local model file index.
/// </summary>
private async Task ClearIndex()
{
await liteDbContext.LocalModelFiles.DeleteAllAsync().ConfigureAwait(false);
}
/// <inheritdoc />
public async Task<IReadOnlyList<LocalModelFile>> GetModelsOfType(SharedFolderType type)
{
return await liteDbContext.LocalModelFiles
.Query()
.Where(m => m.SharedFolderType == type)
1 year ago
.ToArrayAsync()
.ConfigureAwait(false);
}
1 year ago
/// <inheritdoc />
public async Task RefreshIndex()
{
var modelsDir = new DirectoryPath(settingsManager.ModelsDirectory);
// Start
var stopwatch = Stopwatch.StartNew();
logger.LogInformation("Refreshing model index...");
1 year ago
using var db = await liteDbContext.Database.BeginTransactionAsync().ConfigureAwait(false);
var localModelFiles = db.GetCollection<LocalModelFile>("LocalModelFiles")!;
await localModelFiles.DeleteAllAsync().ConfigureAwait(false);
// Record start of actual indexing
var indexStart = stopwatch.Elapsed;
1 year ago
var added = 0;
1 year ago
foreach (
var file in modelsDir.Info
.EnumerateFiles("*.*", SearchOption.AllDirectories)
.Select(info => new FilePath(info))
)
{
// Skip if not supported extension
if (!LocalModelFile.SupportedCheckpointExtensions.Contains(file.Info.Extension))
{
continue;
}
1 year ago
var relativePath = Path.GetRelativePath(modelsDir, file);
1 year ago
// Get shared folder name
1 year ago
var sharedFolderName = relativePath.Split(
Path.DirectorySeparatorChar,
StringSplitOptions.RemoveEmptyEntries
)[0];
// Convert to enum
var sharedFolderType = Enum.Parse<SharedFolderType>(sharedFolderName, true);
1 year ago
var localModel = new LocalModelFile
{
RelativePath = relativePath,
SharedFolderType = sharedFolderType,
};
1 year ago
// Try to find a connected model info
var jsonPath = file.Directory!.JoinFile(
1 year ago
new FilePath(file.NameWithoutExtension, ".cm-info.json")
);
if (jsonPath.Exists)
{
var connectedModelInfo = ConnectedModelInfo.FromJson(
1 year ago
await jsonPath.ReadAllTextAsync().ConfigureAwait(false)
);
localModel.ConnectedModelInfo = connectedModelInfo;
}
1 year ago
// Try to find a preview image
var previewImagePath = LocalModelFile.SupportedImageExtensions
1 year ago
.Select(
ext => file.Directory!.JoinFile($"{file.NameWithoutExtension}.preview{ext}")
)
.FirstOrDefault(path => path.Exists);
if (previewImagePath != null)
{
1 year ago
localModel.PreviewImageRelativePath = Path.GetRelativePath(
modelsDir,
previewImagePath
);
}
1 year ago
// Insert into database
await localModelFiles.InsertAsync(localModel).ConfigureAwait(false);
1 year ago
added++;
}
1 year ago
// Record end of actual indexing
var indexEnd = stopwatch.Elapsed;
1 year ago
await db.CommitAsync().ConfigureAwait(false);
1 year ago
// End
stopwatch.Stop();
var indexDuration = indexEnd - indexStart;
var dbDuration = stopwatch.Elapsed - indexDuration;
1 year ago
logger.LogInformation(
"Model index refreshed with {Entries} entries, took {IndexDuration:F1}ms ({DbDuration:F1}ms db)",
added,
indexDuration.TotalMilliseconds,
dbDuration.TotalMilliseconds
);
}
/// <inheritdoc />
public void BackgroundRefreshIndex() { }
}