Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated Permission Service to simplify caching #1143

Merged
merged 3 commits into from
Aug 16, 2022
Merged

Conversation

darrelmiller
Copy link
Contributor

Overview

To try and minimize memory usage, the caching of permission data has been simplified and no longer uses the recyclable memory stream.

@@ -161,6 +158,10 @@ private string SanitizeUrlQueryPath(string url)
return url;
}

// use the service provider to lazily get an IPermissionsStore instance
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I moved this after the URL check to avoid loading the uriTemplateMatcher from the cache if we are not going to use it.

@@ -50,36 +48,68 @@ public class PermissionsStore : IPermissionsStore
private const string PermissionsContainerBlobConfig = "BlobStorage:Containers:Permissions";
private const string NullValueError = "Value cannot be null";


private class PermissionsDataInfo
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had to create this wrapper class so that LoadPermissionsData could return both the UriTemplateMatcher and the ScopesList. I want to avoid using class level variables because we are going to store this in the cache. This avoids having to keep track of booleans to tell us if the cache is fresh, and it reduces multi-threading issues.

{
get
{
if (!_Cache.TryGetValue<PermissionsDataInfo>("PermissionsData", out var permissionsData))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

If anyone tries to get access to the PermissionsData we go get the reference from the cache. We don't hold it as a field. If we can't get it from the cache, we go load the data and put that in a lock so that a second caller will get blocked until the load is complete.
If the data expires it will be flushed from cache within a minute.

{
_urlTemplateMatcher = new UriTemplateMatcher();
_scopesListTable = new Dictionary<int, object>();
var urlTemplateMatcher = new UriTemplateMatcher();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Class level variables in singleton services are a real pain for multi-threaded apps. Avoid them where you can.

private IDictionary<int, object> _scopesListTable;
private readonly IMemoryCache _permissionsCache;

private readonly IMemoryCache _Cache;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The cache can store anything we need, so let's just call it what it is, a cache.

baywet
baywet previously approved these changes Aug 15, 2022
@sonarqubecloud
Copy link

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 1 Code Smell

88.9% 88.9% Coverage
0.0% 0.0% Duplication

@irvinesunday irvinesunday merged commit 5677600 into dev Aug 16, 2022
@irvinesunday irvinesunday deleted the dm/permissionsperf branch August 16, 2022 20:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Resolve OutOfMemory server errors causing 500 responses
4 participants