Skip to content
This repository was archived by the owner on Nov 20, 2018. It is now read-only.

Allow feature cache to be updated #501

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,43 @@ namespace Microsoft.AspNet.Http.Authentication.Internal
{
public class DefaultAuthenticationManager : AuthenticationManager, IFeatureCache
{
private readonly IFeatureCollection _features;
private IFeatureCollection _features;
private int _cachedFeaturesRevision = -1;

private IHttpAuthenticationFeature _authentication;
private IHttpResponseFeature _response;

public DefaultAuthenticationManager(IFeatureCollection features)
{
_features = features;
((IFeatureCache)this).SetFeaturesRevision();
}

void IFeatureCache.CheckFeaturesRevision()
{
if (_cachedFeaturesRevision != _features.Revision)
{
_authentication = null;
_response = null;
_cachedFeaturesRevision = _features.Revision;
ResetFeatures();
}
}

void IFeatureCache.SetFeaturesRevision()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the explicit implementation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't want someone to call it; as it says "mark cache as up to date; but don't check it" - its only valid use is as part of the Interface contract.

{
_cachedFeaturesRevision = _features.Revision;
}

public void UpdateFeatures(IFeatureCollection features)
{
_features = features;
ResetFeatures();
}

private void ResetFeatures()
{
_authentication = null;

((IFeatureCache)this).SetFeaturesRevision();
}

private IHttpAuthenticationFeature HttpAuthenticationFeature
{
get
Expand All @@ -47,11 +63,6 @@ private IHttpAuthenticationFeature HttpAuthenticationFeature
}
}

private IHttpResponseFeature HttpResponseFeature
{
get { return FeatureHelpers.GetAndCache(this, _features, ref _response); }
}

public override IEnumerable<AuthenticationDescription> GetAuthenticationSchemes()
{
var handler = HttpAuthenticationFeature.Handler;
Expand Down
26 changes: 22 additions & 4 deletions src/Microsoft.AspNet.Http/DefaultConnectionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Microsoft.AspNet.Http.Internal
{
public class DefaultConnectionInfo : ConnectionInfo, IFeatureCache
{
private readonly IFeatureCollection _features;
private IFeatureCollection _features;
private int _cachedFeaturesRevision = -1;

private IHttpConnectionFeature _connection;
Expand All @@ -21,18 +21,36 @@ public class DefaultConnectionInfo : ConnectionInfo, IFeatureCache
public DefaultConnectionInfo(IFeatureCollection features)
{
_features = features;
((IFeatureCache)this).SetFeaturesRevision();
}

void IFeatureCache.CheckFeaturesRevision()
{
if (_cachedFeaturesRevision != _features.Revision)
{
_connection = null;
_tlsConnection = null;
_cachedFeaturesRevision = _features.Revision;
ResetFeatures();
}
}

void IFeatureCache.SetFeaturesRevision()
{
_cachedFeaturesRevision = _features.Revision;
}

public void UpdateFeatures(IFeatureCollection features)
{
_features = features;
ResetFeatures();
}

private void ResetFeatures()
{
_connection = null;
_tlsConnection = null;

((IFeatureCache)this).SetFeaturesRevision();
}

private IHttpConnectionFeature HttpConnectionFeature
{
get
Expand Down
49 changes: 38 additions & 11 deletions src/Microsoft.AspNet.Http/DefaultHttpContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,18 @@ namespace Microsoft.AspNet.Http.Internal
{
public class DefaultHttpContext : HttpContext, IFeatureCache
{
private readonly HttpRequest _request;
private readonly HttpResponse _response;
private ConnectionInfo _connection;
private AuthenticationManager _authenticationManager;
private readonly DefaultHttpRequest _request;
private readonly DefaultHttpResponse _response;

private DefaultAuthenticationManager _authenticationManager;
private DefaultConnectionInfo _connection;
private DefaultWebSocketManager _websockets;

private IItemsFeature _items;
private IServiceProvidersFeature _serviceProviders;
private IHttpAuthenticationFeature _authentication;
private IHttpRequestLifetimeFeature _lifetime;
private ISessionFeature _session;
private WebSocketManager _websockets;

private IFeatureCollection _features;
private int _cachedFeaturesRevision = -1;
Expand All @@ -36,28 +37,54 @@ public DefaultHttpContext()
{
_features.Set<IHttpRequestFeature>(new HttpRequestFeature());
_features.Set<IHttpResponseFeature>(new HttpResponseFeature());
((IFeatureCache)this).SetFeaturesRevision();
}

public DefaultHttpContext(IFeatureCollection features)
{
_features = features;
_request = new DefaultHttpRequest(this, features);
_response = new DefaultHttpResponse(this, features);
((IFeatureCache)this).SetFeaturesRevision();
}

void IFeatureCache.CheckFeaturesRevision()
{
if (_cachedFeaturesRevision !=_features.Revision)
{
_items = null;
_serviceProviders = null;
_authentication = null;
_lifetime = null;
_session = null;
_cachedFeaturesRevision = _features.Revision;
ResetFeatures();
}
}

void IFeatureCache.SetFeaturesRevision()
{
_cachedFeaturesRevision = _features.Revision;
}

public void UpdateFeatures(IFeatureCollection features)
{
_features = features;
ResetFeatures();

_request.UpdateFeatures(features);
_response.UpdateFeatures(features);

_authenticationManager?.UpdateFeatures(features);
_connection?.UpdateFeatures(features);
_websockets?.UpdateFeatures(features);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these lazy sub-objects be cleared out per request? Only some requests will need them. If they don't get cleared then eventually every pooled HttpContext will have all of them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Paid the price; fairly small, are a defined size (rather than an unknown user code type) - might as well? (Happy either way)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shrug It's a probability question. We can figure it out based on profiles later.

}

private void ResetFeatures()
{
_items = null;
_serviceProviders = null;
_authentication = null;
_lifetime = null;
_session = null;

((IFeatureCache)this).SetFeaturesRevision();
}

IItemsFeature ItemsFeature
{
get
Expand Down
30 changes: 24 additions & 6 deletions src/Microsoft.AspNet.Http/DefaultHttpRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Microsoft.AspNet.Http.Internal
public class DefaultHttpRequest : HttpRequest, IFeatureCache
{
private readonly DefaultHttpContext _context;
private readonly IFeatureCollection _features;
private IFeatureCollection _features;
private int _cachedFeaturesRevision = -1;

private IHttpRequestFeature _request;
Expand All @@ -26,20 +26,38 @@ public DefaultHttpRequest(DefaultHttpContext context, IFeatureCollection feature
{
_context = context;
_features = features;
((IFeatureCache)this).SetFeaturesRevision();
}

void IFeatureCache.CheckFeaturesRevision()
{
if (_cachedFeaturesRevision != _features.Revision)
{
_request = null;
_query = null;
_form = null;
_cookies = null;
_cachedFeaturesRevision = _features.Revision;
ResetFeatures();
}
}

void IFeatureCache.SetFeaturesRevision()
{
_cachedFeaturesRevision = _features.Revision;
}

public void UpdateFeatures(IFeatureCollection features)
{
_features = features;
ResetFeatures();
}

private void ResetFeatures()
{
_request = null;
_query = null;
_form = null;
_cookies = null;

((IFeatureCache)this).SetFeaturesRevision();
}

private IHttpRequestFeature HttpRequestFeature
{
get { return FeatureHelpers.GetAndCache(this, _features, ref _request); }
Expand Down
26 changes: 22 additions & 4 deletions src/Microsoft.AspNet.Http/DefaultHttpResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Microsoft.AspNet.Http.Internal
public class DefaultHttpResponse : HttpResponse, IFeatureCache
{
private readonly DefaultHttpContext _context;
private readonly IFeatureCollection _features;
private IFeatureCollection _features;
private int _cachedFeaturesRevision = -1;

private IHttpResponseFeature _response;
Expand All @@ -23,18 +23,36 @@ public DefaultHttpResponse(DefaultHttpContext context, IFeatureCollection featur
{
_context = context;
_features = features;
((IFeatureCache)this).SetFeaturesRevision();
}

void IFeatureCache.CheckFeaturesRevision()
{
if (_cachedFeaturesRevision != _features.Revision)
{
_response = null;
_cookies = null;
_cachedFeaturesRevision = _features.Revision;
ResetFeatures();
}
}

void IFeatureCache.SetFeaturesRevision()
{
_cachedFeaturesRevision = _features.Revision;
}

public void UpdateFeatures(IFeatureCollection features)
{
_features = features;
ResetFeatures();
}

private void ResetFeatures()
{
_response = null;
_cookies = null;

((IFeatureCache)this).SetFeaturesRevision();
}

private IHttpResponseFeature HttpResponseFeature
{
get { return FeatureHelpers.GetAndCache(this, _features, ref _response); }
Expand Down
24 changes: 21 additions & 3 deletions src/Microsoft.AspNet.Http/DefaultWebSocketManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,36 @@ public class DefaultWebSocketManager : WebSocketManager, IFeatureCache
public DefaultWebSocketManager(IFeatureCollection features)
{
_features = features;
((IFeatureCache)this).SetFeaturesRevision();
}

void IFeatureCache.CheckFeaturesRevision()
{
if (_cachedFeaturesRevision != _features.Revision)
{
_request = null;
_webSockets = null;
_cachedFeaturesRevision = _features.Revision;
ResetFeatures();
}
}

void IFeatureCache.SetFeaturesRevision()
{
_cachedFeaturesRevision = _features.Revision;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to also set _cachedFeaturesRevision in the constructor? It would save you work on your first call to CheckFeaturesRevision.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep; done both, just running tests locally.

}

public void UpdateFeatures(IFeatureCollection features)
{
_features = features;
ResetFeatures();
}

private void ResetFeatures()
{
_request = null;
_webSockets = null;

((IFeatureCache)this).SetFeaturesRevision();
}

private IHttpRequestFeature HttpRequestFeature
{
get { return FeatureHelpers.GetAndCache(this, _features, ref _request); }
Expand Down
15 changes: 9 additions & 6 deletions src/Microsoft.AspNet.Http/Features/FeatureHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,10 @@ public static T GetOrCreateAndCache<T>(
if (obj == null)
{
obj = factory();
cachedObject = obj;
features.Set(obj);
}
cachedObject = obj;
features.Set(obj);
cache.SetFeaturesRevision();
}
return obj;
}
Expand All @@ -79,9 +80,10 @@ public static T GetOrCreateAndCache<T>(
if (obj == null)
{
obj = factory(features);
cachedObject = obj;
features.Set(obj);
}
cachedObject = obj;
features.Set(obj);
cache.SetFeaturesRevision();
}
return obj;
}
Expand All @@ -103,9 +105,10 @@ public static T GetOrCreateAndCache<T>(
if (obj == null)
{
obj = factory(request);
cachedObject = obj;
features.Set(obj);
}
cachedObject = obj;
features.Set(obj);
cache.SetFeaturesRevision();
}
return obj;
}
Expand Down
1 change: 1 addition & 0 deletions src/Microsoft.AspNet.Http/Features/IFeatureCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ namespace Microsoft.AspNet.Http.Features
internal interface IFeatureCache
{
void CheckFeaturesRevision();
void SetFeaturesRevision();
}
}
Loading