//
// 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;
}
}
}