-
Notifications
You must be signed in to change notification settings - Fork 50
/
Engine.cs
71 lines (63 loc) · 2.46 KB
/
Engine.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
using System;
using FSharpUtils.Newtonsoft;
using LanguageExt;
using System.Collections.Generic;
using System.Linq;
using Tweek.Engine.Core.Context;
using Tweek.Engine.Core.Rules;
using Tweek.Engine.DataTypes;
using IdentityHashSet = System.Collections.Generic.HashSet<Tweek.Engine.DataTypes.Identity>;
namespace Tweek.Engine.Core
{
public delegate Option<IRule> GetRule(ConfigurationPath path);
public static class EngineCore
{
public delegate Option<ConfigurationValue> GetRuleValue(ConfigurationPath path);
public static GetRuleValue GetRulesEvaluator(IdentityHashSet identities, GetLoadedContextByIdentityType contextByIdentity, GetRule getRule)
{
var identityTypes = identities.Select(x => x.Type).ToArray();
var flattenContext = ContextHelpers.FlattenLoadedContext(contextByIdentity);
GetRuleValue getRuleValue = null;
GetContextValue recursiveContext = key =>
{
if (key.StartsWith("@@key:")){
key = key.Replace("@@key:", "keys.");
}
if (!key.StartsWith("keys.")) return Option<JsonValue>.None;
var path = new ConfigurationPath(key.Split('.')[1]);
return getRuleValue(path).Map(x => x.Value);
};
var context = ContextHelpers.Merge(flattenContext, recursiveContext);
getRuleValue = Memoize(path =>
{
try
{
foreach (var identity in identityTypes)
{
var fixedResult = ContextHelpers.GetFixedConfigurationContext(context, identity)(path);
if (fixedResult.IsSome) return fixedResult;
}
return getRule(path).Bind(x => x.GetValue(context));
}
catch (Exception e)
{
return ConfigurationValue.Error(e);
}
});
return getRuleValue;
}
private static GetRuleValue Memoize(GetRuleValue getRuleValue)
{
var dict = new Dictionary<ConfigurationPath, Option<ConfigurationValue>>();
return path =>
{
if (!dict.TryGetValue(path, out var result))
{
result = getRuleValue(path);
dict[path] = result;
}
return result;
};
}
}
}