diff --git a/src/DevChatter.DevStreams.Core/Services/IChannelSearchService.cs b/src/DevChatter.DevStreams.Core/Services/IChannelSearchService.cs index bb164d2..5fc2349 100644 --- a/src/DevChatter.DevStreams.Core/Services/IChannelSearchService.cs +++ b/src/DevChatter.DevStreams.Core/Services/IChannelSearchService.cs @@ -1,12 +1,10 @@ -using System.Collections.Generic; +using DevChatter.DevStreams.Core.Model; using System.Threading.Tasks; -using DevChatter.DevStreams.Core.Model; namespace DevChatter.DevStreams.Core.Services { public interface IChannelSearchService { - List Find(); Task GetChannelSoundex(string standardizedChannelName); } } \ No newline at end of file diff --git a/src/DevChatter.DevStreams.Infra.Dapper/Services/ChannelSearchService.cs b/src/DevChatter.DevStreams.Infra.Dapper/Services/ChannelSearchService.cs index 3957c8e..5dded81 100644 --- a/src/DevChatter.DevStreams.Infra.Dapper/Services/ChannelSearchService.cs +++ b/src/DevChatter.DevStreams.Infra.Dapper/Services/ChannelSearchService.cs @@ -3,7 +3,6 @@ using DevChatter.DevStreams.Core.Services; using DevChatter.DevStreams.Core.Settings; using Microsoft.Extensions.Options; -using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Linq; @@ -20,29 +19,6 @@ public ChannelSearchService(IOptions databaseSettings) _dbSettings = databaseSettings.Value; } - public List Find() - { - string sql = "SELECT * FROM [ChannelTags] WHERE ChannelId IN @ids"; - using (IDbConnection connection = new SqlConnection(_dbSettings.DefaultConnection)) - { - // TODO: Pull all data in 1 request and/or cache a lot. - var channels = connection.GetList().ToList(); - var tags = connection.GetList().ToList(); // TODO: Cache this. - - List channelIds = channels.Select(c => c.Id).ToList(); - var channelTags = connection.Query(sql, - new { ids = channelIds }).ToList(); - - foreach (var channel in channels) - { - var tagIdsForChannel = channelTags.Where(ct => ct.ChannelId == channel.Id).Select(ct => ct.TagId); - channel.Tags = tags.Where(tag => tagIdsForChannel.Contains(tag.Id)).ToList(); - } - - return channels; - } - } - public async Task GetChannelSoundex(string standardizedChannelName) { var sql = @"SELECT TOP 1 * FROM Channels WHERE SOUNDEX(Name) = SOUNDEX(@standardizedChannelName) diff --git a/src/DevChatter.DevStreams.Infra.GraphQL/DevStreamsQuery.cs b/src/DevChatter.DevStreams.Infra.GraphQL/DevStreamsQuery.cs index 771b52f..be767c4 100644 --- a/src/DevChatter.DevStreams.Infra.GraphQL/DevStreamsQuery.cs +++ b/src/DevChatter.DevStreams.Infra.GraphQL/DevStreamsQuery.cs @@ -1,12 +1,12 @@ -using System.Collections.Generic; -using DevChatter.DevStreams.Core.Data; +using DevChatter.DevStreams.Core.Data; using DevChatter.DevStreams.Core.Model; +using DevChatter.DevStreams.Core.Services; +using DevChatter.DevStreams.Core.Twitch; using DevChatter.DevStreams.Infra.GraphQL.Types; using GraphQL.Types; +using System.Collections.Generic; using System.Linq; -using DevChatter.DevStreams.Core.Services; using System.Threading.Tasks; -using DevChatter.DevStreams.Core.Twitch; namespace DevChatter.DevStreams.Infra.GraphQL { diff --git a/src/DevChatter.DevStreams.Web/Caching/CachedChannelSearchService.cs b/src/DevChatter.DevStreams.Web/Caching/CachedChannelSearchService.cs new file mode 100644 index 0000000..ed34776 --- /dev/null +++ b/src/DevChatter.DevStreams.Web/Caching/CachedChannelSearchService.cs @@ -0,0 +1,35 @@ +using DevChatter.DevStreams.Core.Model; +using DevChatter.DevStreams.Core.Services; +using Microsoft.Extensions.Caching.Memory; +using System; +using System.Threading.Tasks; + +namespace DevChatter.DevStreams.Web.Caching +{ + public class CachedChannelSearchService : IChannelSearchService + { + private readonly IChannelSearchService _searchService; + private readonly IMemoryCache _cacheLayer; + + public CachedChannelSearchService(IChannelSearchService searchService, IMemoryCache cacheLayer) + { + _searchService = searchService; + _cacheLayer = cacheLayer; + } + + public async Task GetChannelSoundex(string standardizedChannelName) + { + string cacheKey = $"{nameof(IChannelSearchService)}-{nameof(GetChannelSoundex)}-{standardizedChannelName}"; + + var channel = await _cacheLayer.GetOrCreateAsync(cacheKey, CacheFallback); + + return channel; + + Task CacheFallback(ICacheEntry entry) + { + entry.SetAbsoluteExpiration(TimeSpan.FromMinutes(15)); // TODO: Store in Config Setting + return _searchService.GetChannelSoundex(standardizedChannelName); + } + } + } +} \ No newline at end of file diff --git a/src/DevChatter.DevStreams.Web/Startup.cs b/src/DevChatter.DevStreams.Web/Startup.cs index 1815d5f..8664b5d 100644 --- a/src/DevChatter.DevStreams.Web/Startup.cs +++ b/src/DevChatter.DevStreams.Web/Startup.cs @@ -2,12 +2,14 @@ using DevChatter.DevStreams.Core.Data; using DevChatter.DevStreams.Core.Services; using DevChatter.DevStreams.Core.Settings; +using DevChatter.DevStreams.Core.Twitch; using DevChatter.DevStreams.Infra.Dapper; using DevChatter.DevStreams.Infra.Dapper.Services; using DevChatter.DevStreams.Infra.Dapper.TypeHandlers; using DevChatter.DevStreams.Infra.Db.Migrations; using DevChatter.DevStreams.Infra.GraphQL; using DevChatter.DevStreams.Infra.Twitch; +using DevChatter.DevStreams.Web.Caching; using DevChatter.DevStreams.Web.Data; using FluentMigrator.Runner; using GraphQL.Server; @@ -18,15 +20,13 @@ using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using NodaTime; using System; using System.Linq; using System.Threading.Tasks; -using DevChatter.DevStreams.Core.Twitch; -using DevChatter.DevStreams.Web.Caching; -using Microsoft.Extensions.Caching.Memory; namespace DevChatter.DevStreams.Web { @@ -100,7 +100,6 @@ public void ConfigureServices(IServiceCollection services) services.AddTransient(); services.AddTransient(); services.AddScoped(); - services.AddTransient(); services.AddTransient(); services.AddMemoryCache(); @@ -109,6 +108,10 @@ public void ConfigureServices(IServiceCollection services) CachedTwitchStreamService TwitchServiceFactory(IServiceProvider x) => new CachedTwitchStreamService((ITwitchStreamService) x.GetService(typeof(TwitchStreamService)), (IMemoryCache)x.GetService(typeof(IMemoryCache))); services.AddScoped(TwitchServiceFactory); + services.AddScoped(); + CachedChannelSearchService ChannelSearchServiceFactory(IServiceProvider x) => new CachedChannelSearchService((IChannelSearchService) x.GetService(typeof(ChannelSearchService)), (IMemoryCache)x.GetService(typeof(IMemoryCache))); + services.AddScoped(ChannelSearchServiceFactory); + services.AddScoped(); services.AddSingleton(SystemClock.Instance);