diff --git a/Deployment/ConfigurationBootstrapper.cs b/Deployment/ConfigurationBootstrapper.cs deleted file mode 100644 index 10da8d9..0000000 --- a/Deployment/ConfigurationBootstrapper.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Dynamic; -using System.Reflection; -using System.Runtime.CompilerServices; -using Newtonsoft.Json; - -[assembly: InternalsVisibleTo("deployment.tests")] -namespace greyn.Deployment -{ - public static class ConfigurationBootstrapper - { - private const string confpath = "appsettings.json"; - - public static T Load() where T : new() - { - if (File.Exists("appsettings.json")) - { - /* - * if the configuration expects new values we write them in. - * if you left other junk for whatever reason, get rekt - */ - var toReturn = JsonConvert.DeserializeObject(File.ReadAllText(confpath)) ?? new T(); - File.WriteAllText(confpath, JsonConvert.SerializeObject(toReturn, Formatting.Indented)); - return toReturn; - } - else - { - var toReturn = new T(); - File.WriteAllText(confpath, JsonConvert.SerializeObject(toReturn)); - return toReturn; - } - } - } -} diff --git a/Deployment/Configurator.cs b/Deployment/Configurator.cs new file mode 100644 index 0000000..189ccb2 --- /dev/null +++ b/Deployment/Configurator.cs @@ -0,0 +1,71 @@ +using System; +using System.Dynamic; +using System.Reflection; +using System.Runtime.CompilerServices; +using Newtonsoft.Json; + +[assembly: InternalsVisibleTo("deployment.tests")] +namespace greyn.Deployment +{ + public static class Configurator where T : new() + { + private const string confpath = "appsettings.json"; + private static FileSystemWatcher appsettingsWatcher = new FileSystemWatcher("."); + + public static event EventHandler Changed; + public static event System.IO.ErrorEventHandler Error; + + private static T config; + + public static T Load() + { + if (File.Exists(confpath)) + { + /* + * if the configuration expects new values we write them in. + * if you left other junk for whatever reason, get rekt + */ + config = JsonConvert.DeserializeObject(File.ReadAllText(confpath)) ?? new T(); + } + else + { + config = new T(); + } + File.WriteAllText(confpath, JsonConvert.SerializeObject(config, Formatting.Indented)); + + + + + appsettingsWatcher.Filter = confpath; + + appsettingsWatcher.NotifyFilter = NotifyFilters.LastWrite + | NotifyFilters.Security + | NotifyFilters.Size; + + appsettingsWatcher.Changed += internalOnChanged; + appsettingsWatcher.Created += internalOnChanged; + appsettingsWatcher.Deleted += internalOnChanged; + appsettingsWatcher.Renamed += internalOnChanged; + appsettingsWatcher.Error += Error; + + appsettingsWatcher.EnableRaisingEvents = true; + + return config; + } + + internal static void internalOnChanged(object sender, FileSystemEventArgs e) + { + appsettingsWatcher.EnableRaisingEvents = false; + + Load(); + Changed(sender, new ConfigChangedEventArgs(){NewConfig = config}); + } + + //I would like to just pudate the values on our held reference, but we'd have to update each value by reflection. + //2lazy. + public class ConfigChangedEventArgs : EventArgs + { + public T NewConfig; + } + } +} diff --git a/deployment.tests/ConfigTests.cs b/deployment.tests/ConfigTests.cs index 8bde90a..d6245cd 100644 --- a/deployment.tests/ConfigTests.cs +++ b/deployment.tests/ConfigTests.cs @@ -56,12 +56,6 @@ public class ConfigTests aValueTypeButNotAField = ""796.651"", }"; #endregion - - [Test] - public void vibecheck() - { - Assert.AreEqual(0, new Random().Next(0, 2)); - } [TearDown] public void TearDown() @@ -69,29 +63,32 @@ public class ConfigTests if(File.Exists("appsettings.json")) File.Delete("appsettings.json"); } +/* [Test] public void load_doesnt_explode() { File.WriteAllText("appsettings.json", PerfectConfiguration); - var conf = greyn.Deployment.ConfigurationBootstrapper.Load(); + var conf = greyn.Deployment.Configurator.Load(); Assert.Pass(); } + */ [Test] public void load_loads() { File.WriteAllText("appsettings.json", PerfectConfiguration); - var conf = greyn.Deployment.ConfigurationBootstrapper.Load(); + var conf = greyn.Deployment.Configurator.Load(); - Assert.AreEqual(conf.aValueTypeButNotAField, 796.651f); - Assert.AreEqual(conf.aField, "I've decided"); - Assert.AreEqual(conf.subtyped.aValueType, 94.298); - Assert.AreEqual(conf.subtyped.aValueTypeButNotAField, 9241); + Assert.AreEqual(796.651f, conf.aValueTypeButNotAField); + Assert.AreEqual("I've decided", conf.aField); + Assert.AreEqual(94.298, conf.subtyped.aValueType); + Assert.AreEqual(9241, conf.subtyped.aValueTypeButNotAField); Assert.IsNotNull(conf.subtyped.anEnumerableType); - Assert.AreEqual(conf.subtyped.anEnumerableType["test3"], 420.71); - Assert.AreEqual(conf.subtyped.anEnumerableType["test4"], 420.72); + Assert.AreEqual( 420.71, conf.subtyped.anEnumerableType["test3"]); + Assert.AreEqual( 420.72, conf.subtyped.anEnumerableType["test4"]); Assert.IsNotNull(conf.subtyped2); } + /* [Test] public void load_acceptsnullasvalue() { @@ -116,23 +113,24 @@ public class ConfigTests } }"); - var conf = greyn.Deployment.ConfigurationBootstrapper.Load(); + var conf = greyn.Deployment.Configurator.Load(); + System.Threading.Thread.Sleep(1000); - Assert.AreEqual(conf.aValueTypeButNotAField, 796.651f); - Assert.AreEqual(conf.aField, "I've decided"); - Assert.AreEqual(conf.subtyped.aValueType, 94.298); - Assert.AreEqual(conf.subtyped.aValueTypeButNotAField, 9241); + Assert.AreEqual(796.651f, conf.aValueTypeButNotAField); + Assert.AreEqual("I've decided", conf.aField); + Assert.AreEqual(94.298, conf.subtyped.aValueType); + Assert.AreEqual(9241, conf.subtyped.aValueTypeButNotAField); Assert.IsNotNull(conf.subtyped); Assert.IsNull(conf.subtyped.anEnumerableType); Assert.IsNotNull(conf.subtyped2); - Assert.AreEqual(conf.subtyped2.aValueType, 95.298); - Assert.AreEqual(conf.subtyped2.aValueTypeButNotAField, 9242); + Assert.AreEqual(95.298, conf.subtyped2.aValueType); + Assert.AreEqual(9242, conf.subtyped2.aValueTypeButNotAField); Assert.IsNotNull(conf.subtyped2.anEnumerableType); - Assert.AreEqual(conf.subtyped2.anEnumerableType["test5"], 420.73); - Assert.AreEqual(conf.subtyped2.anEnumerableType["test6"], 420.74); + Assert.AreEqual( 420.73, conf.subtyped2.anEnumerableType["test5"]); + Assert.AreEqual( 420.74, conf.subtyped2.anEnumerableType["test6"]); } [Test] public void load_acceptsnull_forparenttype() @@ -152,19 +150,20 @@ public class ConfigTests } } }"); - var conf = greyn.Deployment.ConfigurationBootstrapper.Load(); + var conf = greyn.Deployment.Configurator.Load(); + System.Threading.Thread.Sleep(1000); - Assert.AreEqual(conf.aValueTypeButNotAField, 796.651f); - Assert.AreEqual(conf.aField, "I've decided"); + Assert.AreEqual(796.651f, conf.aValueTypeButNotAField); + Assert.AreEqual("I've decided", conf.aField); Assert.IsNull(conf.subtyped); Assert.IsNotNull(conf.subtyped2); - Assert.AreEqual(conf.subtyped2.aValueType, 95.298); - Assert.AreEqual(conf.subtyped2.aValueTypeButNotAField, 9242); + Assert.AreEqual(95.298, conf.subtyped2.aValueType); + Assert.AreEqual(9242, conf.subtyped2.aValueTypeButNotAField); Assert.IsNotNull(conf.subtyped2.anEnumerableType); - Assert.AreEqual(conf.subtyped2.anEnumerableType["test5"], 420.73); - Assert.AreEqual(conf.subtyped2.anEnumerableType["test6"], 420.74); + Assert.AreEqual( 420.73, conf.subtyped2.anEnumerableType["test5"]); + Assert.AreEqual( 420.74, conf.subtyped2.anEnumerableType["test6"]); } [Test] public void load_usesdefaultfornullablemissing() @@ -193,15 +192,16 @@ public class ConfigTests } } }"); - var conf = greyn.Deployment.ConfigurationBootstrapper.Load(); + var conf = greyn.Deployment.Configurator.Load(); + System.Threading.Thread.Sleep(1000); - Assert.AreEqual(conf.aValueTypeButNotAField, 796.651f); - Assert.AreEqual(conf.aField, "hi there, hello"); - Assert.AreEqual(conf.subtyped.aValueType, 94.298); - Assert.AreEqual(conf.subtyped.aValueTypeButNotAField, 9241); + Assert.AreEqual(796.651f, conf.aValueTypeButNotAField); + Assert.AreEqual("hi there, hello", conf.aField); + Assert.AreEqual(94.298, conf.subtyped.aValueType); + Assert.AreEqual(9241, conf.subtyped.aValueTypeButNotAField); Assert.IsNotNull(conf.subtyped.anEnumerableType); - Assert.AreEqual(conf.subtyped.anEnumerableType["test3"], 420.71); - Assert.AreEqual(conf.subtyped.anEnumerableType["test4"], 420.72); + Assert.AreEqual( 420.71, conf.subtyped.anEnumerableType["test3"]); + Assert.AreEqual( 420.72, conf.subtyped.anEnumerableType["test4"]); Assert.IsNotNull(conf.subtyped2); } [Test] @@ -231,15 +231,87 @@ public class ConfigTests } }"); - var conf = greyn.Deployment.ConfigurationBootstrapper.Load(); + var conf = greyn.Deployment.Configurator.Load(); + System.Threading.Thread.Sleep(1000); - Assert.AreEqual(conf.aValueTypeButNotAField, 156.697f); - Assert.AreEqual(conf.aField, "I've decided"); - Assert.AreEqual(conf.subtyped.aValueType, 94.298); - Assert.AreEqual(conf.subtyped.aValueTypeButNotAField, 9241); + Assert.AreEqual(156.697f, conf.aValueTypeButNotAField); + Assert.AreEqual("I've decided", conf.aField); + Assert.AreEqual(94.298, conf.subtyped.aValueType); + Assert.AreEqual(9241, conf.subtyped.aValueTypeButNotAField); Assert.IsNotNull(conf.subtyped.anEnumerableType); - Assert.AreEqual(conf.subtyped.anEnumerableType["test3"], 420.71); - Assert.AreEqual(conf.subtyped.anEnumerableType["test4"], 420.72); + Assert.AreEqual( 420.71, conf.subtyped.anEnumerableType["test3"]); + Assert.AreEqual( 420.72, conf.subtyped.anEnumerableType["test4"]); Assert.IsNotNull(conf.subtyped2); } +*/ + + [Test] + public void live_reload() + { + File.WriteAllText("appsettings.json", @"{ + aField: ""I've decided"", + subtyped: + { + aValueType: 94.298, + aValueTypeButNotAField: 9241, + anEnumerableType: + { + ""test3"": 420.71, + ""test4"": 420.72 + } + }, + subtyped2: + { + aValueType: 95.298, + aValueTypeButNotAField: 9242, + anEnumerableType: + { + ""test5"": 420.73, + ""test6"": 420.74 + } + } + }"); + + var conf = greyn.Deployment.Configurator.Load(); + System.Threading.Thread.Sleep(1000); + + Assert.AreEqual(94.298, conf.subtyped.aValueType); + + var wait= true; + greyn.Deployment.Configurator.Changed += (sender, e) => { + conf = (e as Configurator.ConfigChangedEventArgs).NewConfig; + wait = false; + }; + +File.WriteAllText("appsettings.json", @"{ + aField: ""I've decided"", + subtyped: + { + aValueType: 94.301, + aValueTypeButNotAField: 9241, + anEnumerableType: + { + ""test3"": 420.71, + ""test4"": 420.72 + } + }, + subtyped2: + { + aValueType: 95.298, + aValueTypeButNotAField: 9242, + anEnumerableType: + { + ""test5"": 420.73, + ""test6"": 420.74 + } + } + }"); + + while(wait) + { + System.Threading.Thread.Sleep(1000); + } + + Assert.AreEqual(94.301, conf.subtyped.aValueType); + } }