// // Copyright (c) PlaceholderCompany. All rights reserved. // namespace Jellyfin.Server.Implementations.Database; using System; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Npgsql; /// /// Ensures supplementary performance indexes exist on database startup. /// public class SupplementaryIndexChecker { private readonly ILogger _logger; private readonly DbContext _context; /// /// Initializes a new instance of the class. /// /// The logger. /// The database context. public SupplementaryIndexChecker(ILogger logger, DbContext context) { _logger = logger; _context = context; } /// /// Checks if supplementary indexes exist and logs warnings if they don't. /// /// Cancellation token. /// True if all indexes exist, false otherwise. public async Task CheckSupplementaryIndexesAsync(CancellationToken cancellationToken = default) { try { var connection = _context.Database.GetDbConnection(); await connection.OpenAsync(cancellationToken).ConfigureAwait(false); var checkQuery = @" SELECT COUNT(*) FROM pg_indexes WHERE indexname IN ( 'idx_baseitems_type_isvirtualitem_topparentid', 'idx_baseitems_topparentid_isfolder', 'idx_baseitems_datecreated_filtered', 'idx_itemvaluesmap_itemvalueid_itemid', 'idx_activitylogs_userid_datecreated' )"; await using var command = connection.CreateCommand(); command.CommandText = checkQuery; var result = await command.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false); var indexCount = Convert.ToInt32(result); if (indexCount < 5) { _logger.LogWarning( "Only {IndexCount}/5 supplementary performance indexes found. " + "Run 'sql/schema_init/10_create_supplementary_indexes.sql' to add missing indexes for better performance.", indexCount); return false; } _logger.LogInformation("All supplementary performance indexes are present ({IndexCount}/5).", indexCount); return true; } catch (Exception ex) { _logger.LogError(ex, "Failed to check supplementary indexes"); return false; } } }