New: All setting values are cached for better responsiveness.

pull/3113/head
kay.one 13 years ago
parent 2051c9d911
commit 6df184b7cb

@ -1,7 +1,9 @@
using System; using System;
using System.IO; using System.IO;
using NUnit.Framework;
using NzbDrone.Common; using NzbDrone.Common;
using NzbDrone.Core.Model.Notification; using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Test.Common; using NzbDrone.Test.Common;
using PetaPoco; using PetaPoco;
@ -60,5 +62,11 @@ namespace NzbDrone.Core.Test.Framework
return new ProgressNotification("Mock notification"); return new ProgressNotification("Mock notification");
} }
} }
[TearDown]
public void CoreTestTearDown()
{
ConfigProvider.ClearCache();
}
} }
} }

@ -113,6 +113,7 @@
<Compile Include="JobTests\BannerDownloadJobTest.cs" /> <Compile Include="JobTests\BannerDownloadJobTest.cs" />
<Compile Include="JobTests\RecentBacklogSearchJobTest.cs" /> <Compile Include="JobTests\RecentBacklogSearchJobTest.cs" />
<Compile Include="ProviderTests\AnalyticsProviderTests\AnalyticsProviderFixture.cs" /> <Compile Include="ProviderTests\AnalyticsProviderTests\AnalyticsProviderFixture.cs" />
<Compile Include="ProviderTests\ConfigProviderTests\ConfigCachingFixture.cs" />
<Compile Include="ProviderTests\DecisionEngineTests\QualityAllowedByProfileSpecificationFixtrue.cs" /> <Compile Include="ProviderTests\DecisionEngineTests\QualityAllowedByProfileSpecificationFixtrue.cs" />
<Compile Include="ProviderTests\DecisionEngineTests\UpgradeHistorySpecificationFixtrue.cs" /> <Compile Include="ProviderTests\DecisionEngineTests\UpgradeHistorySpecificationFixtrue.cs" />
<Compile Include="ProviderTests\DecisionEngineTests\UpgradeDiskSpecificationFixtrue.cs" /> <Compile Include="ProviderTests\DecisionEngineTests\UpgradeDiskSpecificationFixtrue.cs" />
@ -172,7 +173,7 @@
<Compile Include="ProviderTests\IndexerProviderTest.cs" /> <Compile Include="ProviderTests\IndexerProviderTest.cs" />
<Compile Include="ProviderTests\HistoryProviderTest.cs" /> <Compile Include="ProviderTests\HistoryProviderTest.cs" />
<Compile Include="ProviderTests\MediaFileProviderTest.cs" /> <Compile Include="ProviderTests\MediaFileProviderTest.cs" />
<Compile Include="ProviderTests\ConfigProviderTest.cs" /> <Compile Include="ProviderTests\ConfigProviderTests\ConfigProviderFixture.cs" />
<Compile Include="ProviderTests\EpisodeProviderTest.cs" /> <Compile Include="ProviderTests\EpisodeProviderTest.cs" />
<Compile Include="Framework\TestDbHelper.cs" /> <Compile Include="Framework\TestDbHelper.cs" />
<Compile Include="ParserTest.cs" /> <Compile Include="ParserTest.cs" />

@ -0,0 +1,35 @@
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Test.Framework;
using PetaPoco;
namespace NzbDrone.Core.Test.ProviderTests.ConfigProviderTests
{
[TestFixture]
public class ConfigCachingFixture : CoreTest
{
[SetUp]
public void Setup()
{
Mocker.GetMock<IDatabase>().Setup(c => c.Fetch<Config>())
.Returns(new List<Config> { new Config { Key = "Key1", Value = "Value1" } });
}
[Test]
public void getting_value_more_than_once_should_hit_db_once()
{
Mocker.Resolve<ConfigProvider>().GetValue("Key1", null).Should().Be("Value1");
Mocker.Resolve<ConfigProvider>().GetValue("Key1", null).Should().Be("Value1");
Mocker.Resolve<ConfigProvider>().GetValue("Key1", null).Should().Be("Value1");
Mocker.GetMock<IDatabase>().Verify(c => c.Fetch<Config>(), Times.Once());
}
}
}

@ -6,11 +6,11 @@ using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository; using NzbDrone.Core.Repository;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.ProviderTests namespace NzbDrone.Core.Test.ProviderTests.ConfigProviderTests
{ {
[TestFixture] [TestFixture]
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
public class ConfigProviderTest : CoreTest public class ConfigProviderFixture : CoreTest
{ {
[SetUp] [SetUp]
public void SetUp() public void SetUp()
@ -134,6 +134,15 @@ namespace NzbDrone.Core.Test.ProviderTests
guid.Should().NotBeEmpty(); guid.Should().NotBeEmpty();
} }
[Test]
public void updating_a_vakye_should_update_its_value()
{
Mocker.Resolve<ConfigProvider>().SabHost = "Test";
Mocker.Resolve<ConfigProvider>().SabHost.Should().Be("Test");
Mocker.Resolve<ConfigProvider>().SabHost = "Test2";
Mocker.Resolve<ConfigProvider>().SabHost.Should().Be("Test2");
}
[Test] [Test]
[Description("This test will use reflection to ensure each config property read/writes to a unique key")] [Description("This test will use reflection to ensure each config property read/writes to a unique key")]

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Ninject; using Ninject;
using NLog; using NLog;
using NzbDrone.Core.Model; using NzbDrone.Core.Model;
@ -11,7 +12,10 @@ namespace NzbDrone.Core.Providers.Core
{ {
public class ConfigProvider public class ConfigProvider
{ {
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private static readonly Logger logger = LogManager.GetCurrentClassLogger();
private static Dictionary<string, string> cache = new Dictionary<string, string>();
private readonly IDatabase _database; private readonly IDatabase _database;
[Inject] [Inject]
@ -24,7 +28,7 @@ namespace NzbDrone.Core.Providers.Core
{ {
} }
public IList<Config> All() public IEnumerable<Config> All()
{ {
return _database.Fetch<Config>(); return _database.Fetch<Config>();
} }
@ -449,12 +453,15 @@ namespace NzbDrone.Core.Providers.Core
public virtual string GetValue(string key, object defaultValue, bool persist = false) public virtual string GetValue(string key, object defaultValue, bool persist = false)
{ {
var dbValue = _database.SingleOrDefault<Config>("WHERE [Key] =@0", key); EnsureCache();
if (dbValue != null && !String.IsNullOrEmpty(dbValue.Value)) string dbValue;
return dbValue.Value;
Logger.Trace("Unable to find config key '{0}' defaultValue:'{1}'", key, defaultValue); if (cache.TryGetValue(key, out dbValue) && dbValue != null && !String.IsNullOrEmpty(dbValue))
return dbValue;
logger.Trace("Unable to find config key '{0}' defaultValue:'{1}'", key, defaultValue);
if (persist) if (persist)
SetValue(key, defaultValue.ToString()); SetValue(key, defaultValue.ToString());
@ -479,7 +486,7 @@ namespace NzbDrone.Core.Providers.Core
if (value == null) if (value == null)
throw new ArgumentNullException("key"); throw new ArgumentNullException("key");
Logger.Trace("Writing Setting to file. Key:'{0}' Value:'{1}'", key, value); logger.Trace("Writing Setting to file. Key:'{0}' Value:'{1}'", key, value);
var dbValue = _database.SingleOrDefault<Config>("WHERE [KEY]=@0", key); var dbValue = _database.SingleOrDefault<Config>("WHERE [KEY]=@0", key);
@ -490,11 +497,28 @@ namespace NzbDrone.Core.Providers.Core
else else
{ {
dbValue.Value = value; dbValue.Value = value;
using (var tran = _database.GetTransaction())
{
_database.Update(dbValue); _database.Update(dbValue);
tran.Complete();
} }
ClearCache();
}
private void EnsureCache()
{
lock (cache)
{
if (!cache.Any())
{
cache = _database.Fetch<Config>().ToDictionary(c => c.Key, c => c.Value);
}
}
}
public static void ClearCache()
{
lock (cache)
{
cache = new Dictionary<string, string>();
} }
} }
} }

@ -84,8 +84,8 @@ namespace NzbDrone.Web.Controllers
return Json(new return Json(new
{ {
iTotalRecords = config.Count, iTotalRecords = config.Count(),
iTotalDisplayRecords = config.Count, iTotalDisplayRecords = config.Count(),
aaData = config aaData = config
}, JsonRequestBehavior.AllowGet); }, JsonRequestBehavior.AllowGet);
} }

Loading…
Cancel
Save