Stream custom live channels using your own media
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.
 
 
 

91 lines
2.6 KiB

using System.Text.RegularExpressions;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Search;
using ErsatzTV.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
namespace ErsatzTV.Infrastructure.Search;
public sealed class SmartCollectionCache(IDbContextFactory<TvContext> dbContextFactory)
: ISmartCollectionCache, IDisposable
{
private readonly Dictionary<string, SmartCollectionData> _data = new(StringComparer.OrdinalIgnoreCase);
private readonly SemaphoreSlim _semaphoreSlim = new(1, 1);
private readonly AdjGraph _graph = new();
public async Task Refresh()
{
await _semaphoreSlim.WaitAsync();
try
{
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync();
List<SmartCollection> smartCollections = await dbContext.SmartCollections
.AsNoTracking()
.ToListAsync();
_data.Clear();
_graph.Clear();
foreach (SmartCollection smartCollection in smartCollections)
{
var data = new SmartCollectionData(smartCollection.Query);
_data.Add(smartCollection.Name, data);
foreach (Match match in SearchQueryParser.SmartCollectionRegex().Matches(smartCollection.Query))
{
string otherCollectionName = match.Groups[1].Value;
_graph.AddEdge(smartCollection.Name, otherCollectionName);
}
}
foreach (SmartCollection smartCollection in smartCollections)
{
SmartCollectionData data = _data[smartCollection.Name];
data.HasCycle = _graph.HasCycle(smartCollection.Name);
}
}
finally
{
_semaphoreSlim.Release();
}
}
public async Task<bool> HasCycle(string name)
{
await _semaphoreSlim.WaitAsync();
try
{
return _data.TryGetValue(name, out SmartCollectionData data) && data.HasCycle;
}
finally
{
_semaphoreSlim.Release();
}
}
public async Task<Option<string>> GetQuery(string name)
{
await _semaphoreSlim.WaitAsync();
try
{
return _data.TryGetValue(name, out SmartCollectionData data) ? data.Query : Option<string>.None;
}
finally
{
_semaphoreSlim.Release();
}
}
public void Dispose()
{
_semaphoreSlim.Dispose();
}
private record SmartCollectionData(string Query)
{
public bool HasCycle { get; set; }
}
}