Skip to content

Commit 6abaa0d

Browse files
update
1 parent cd94d26 commit 6abaa0d

File tree

2 files changed

+46
-53
lines changed

2 files changed

+46
-53
lines changed

src/Microsoft.FeatureManagement/FeatureFilters/TimeWindowFilter.cs

Lines changed: 29 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,10 @@ public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context)
8888
if (settings.Recurrence != null)
8989
{
9090
//
91-
// The reference of the object will be used for hash key.
91+
// The reference of the object will be used for cache key.
9292
// If there is no pre-bounded settings attached to the context, there will be no cached filter settings and each call will have a unique settings object.
9393
// In this case, the cache for recurrence settings won't work.
94-
if (context.Settings == null || Cache == null)
94+
if (Cache == null || context.Settings == null)
9595
{
9696
return Task.FromResult(RecurrenceEvaluator.IsMatch(now, settings));
9797
}
@@ -100,52 +100,45 @@ public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context)
100100
// The start time of the closest active time window. It could be null if the recurrence range surpasses its end.
101101
DateTimeOffset? closestStart;
102102

103-
if (!Cache.TryGetValue(settings, out closestStart))
103+
TimeSpan activeDuration = settings.End.Value - settings.Start.Value;
104+
105+
//
106+
// Recalculate the closest start if not yet calculated,
107+
// Or if we have passed the cached time window.
108+
if (!Cache.TryGetValue(settings, out closestStart) ||
109+
(closestStart.HasValue && now >= closestStart.Value + activeDuration))
104110
{
105-
closestStart = RecurrenceEvaluator.CalculateClosestStart(now, settings);
106-
107-
Cache.Set(
108-
settings,
109-
closestStart,
110-
new MemoryCacheEntryOptions
111-
{
112-
SlidingExpiration = ParametersCacheSlidingExpiration,
113-
AbsoluteExpirationRelativeToNow = ParametersCacheAbsoluteExpirationRelativeToNow,
114-
Size = 1
115-
});
111+
closestStart = ReloadClosestStart(settings);
116112
}
117113

118-
if (closestStart == null || now < closestStart.Value)
114+
if (!closestStart.HasValue || now < closestStart.Value)
119115
{
120116
return Task.FromResult(false);
121117
}
122118

123-
if (now < closestStart.Value + (settings.End.Value - settings.Start.Value))
124-
{
125-
return Task.FromResult(true);
126-
}
119+
return Task.FromResult(now < closestStart.Value + activeDuration);
120+
}
127121

128-
closestStart = RecurrenceEvaluator.CalculateClosestStart(now, settings);
122+
return Task.FromResult(false);
123+
}
129124

130-
Cache.Set(
131-
settings,
132-
closestStart,
133-
new MemoryCacheEntryOptions
134-
{
135-
SlidingExpiration = ParametersCacheSlidingExpiration,
136-
AbsoluteExpirationRelativeToNow = ParametersCacheAbsoluteExpirationRelativeToNow,
137-
Size = 1
138-
});
125+
private DateTimeOffset? ReloadClosestStart(TimeWindowFilterSettings settings)
126+
{
127+
DateTimeOffset now = SystemClock?.UtcNow ?? DateTimeOffset.UtcNow;
139128

140-
if (closestStart == null || now < closestStart.Value)
141-
{
142-
return Task.FromResult(false);
143-
}
129+
DateTimeOffset? closestStart = RecurrenceEvaluator.CalculateClosestStart(now, settings);
144130

145-
return Task.FromResult(now < closestStart.Value + (settings.End.Value - settings.Start.Value));
146-
}
131+
Cache.Set(
132+
settings,
133+
closestStart,
134+
new MemoryCacheEntryOptions
135+
{
136+
SlidingExpiration = ParametersCacheSlidingExpiration,
137+
AbsoluteExpirationRelativeToNow = ParametersCacheAbsoluteExpirationRelativeToNow,
138+
Size = 1
139+
});
147140

148-
return Task.FromResult(false);
141+
return closestStart;
149142
}
150143
}
151144
}

src/Microsoft.FeatureManagement/FeatureManagementBuilder.cs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,23 @@ public IFeatureManagementBuilder AddFeatureFilter<T>() where T : IFeatureFilterM
5353
return this;
5454
}
5555

56-
public IFeatureManagementBuilder AddFeatureFilter<T>(Func<IServiceProvider, object> implementationFactory) where T : IFeatureFilterMetadata
56+
public IFeatureManagementBuilder AddSessionManager<T>() where T : ISessionManager
57+
{
58+
//
59+
// Register the session manager with the same lifetime as the feature manager
60+
if (Services.Any(descriptor => descriptor.ServiceType == typeof(IFeatureManager) && descriptor.Lifetime == ServiceLifetime.Scoped))
61+
{
62+
Services.AddScoped(typeof(ISessionManager), typeof(T));
63+
}
64+
else
65+
{
66+
Services.AddSingleton(typeof(ISessionManager), typeof(T));
67+
}
68+
69+
return this;
70+
}
71+
72+
internal IFeatureManagementBuilder AddFeatureFilter<T>(Func<IServiceProvider, object> implementationFactory) where T : IFeatureFilterMetadata
5773
{
5874
Type serviceType = typeof(IFeatureFilterMetadata);
5975

@@ -84,21 +100,5 @@ public IFeatureManagementBuilder AddFeatureFilter<T>(Func<IServiceProvider, obje
84100

85101
return this;
86102
}
87-
88-
public IFeatureManagementBuilder AddSessionManager<T>() where T : ISessionManager
89-
{
90-
//
91-
// Register the session manager with the same lifetime as the feature manager
92-
if (Services.Any(descriptor => descriptor.ServiceType == typeof(IFeatureManager) && descriptor.Lifetime == ServiceLifetime.Scoped))
93-
{
94-
Services.AddScoped(typeof(ISessionManager), typeof(T));
95-
}
96-
else
97-
{
98-
Services.AddSingleton(typeof(ISessionManager), typeof(T));
99-
}
100-
101-
return this;
102-
}
103103
}
104104
}

0 commit comments

Comments
 (0)