Skip to content

Commit

Permalink
Rename configuration properties for for HybridCachePlugin
Browse files Browse the repository at this point in the history
All properties have been renamed and are now in Megabytes rather than bytes
  • Loading branch information
lilith committed Oct 14, 2022
1 parent 90fd5d5 commit da51052
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 38 deletions.
2 changes: 1 addition & 1 deletion CHANGES.md
Expand Up @@ -32,7 +32,7 @@
* Delete references to `DiskCache` and `TinyCache` from **both nuget.config and Web.config**
* `Install-Package ImageResizer.Plugins.HybridCache`
* Put `<add name="HybridCache" />` in the `<resizer><plugins>` section of `Web.config`
* Put `<hybridCache cacheLocation="C:\imageresizercache\" cacheMaxSizeBytes="1,000,000,000" />` in the `<resizer>` section of `Web.config`. If you want to use a temp folder, omit cacheLocation.
* Put `<hybridCache cacheLocation="C:\imageresizercache\" cacheSizeMb="1,000" />` in the `<resizer>` section of `Web.config`. If you want to use a temp folder, omit cacheLocation.
* HybridCache requires a cache folder outside of the web root. DiskCache did not support that.
* HybridCache, unlike DiskCache, can precisely limit the cache size & disk utilization.
* HybridCache uses a write-ahead log to prevent orphaned cache entries.
Expand Down
1 change: 0 additions & 1 deletion ImageResizer.sln
Expand Up @@ -40,7 +40,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
CONTRIBUTING.md = CONTRIBUTING.md
.github\workflows\dotnet.yml = .github\workflows\dotnet.yml
LICENSE.md = LICENSE.md
.github\workflows\outdated-dotnet-sweep.yml = .github\workflows\outdated-dotnet-sweep.yml
nuget\NugetPackages.targets = nuget\NugetPackages.targets
.editorconfig = .editorconfig
tests\api-surface\ImageResizer.Plugins.AzureReader2.txt = tests\api-surface\ImageResizer.Plugins.AzureReader2.txt
Expand Down
12 changes: 6 additions & 6 deletions plugins/ImageResizer.Plugins.HybridCache/HybridCacheOptions.cs
Expand Up @@ -5,26 +5,26 @@ namespace ImageResizer.Plugins.HybridCache
public class HybridCacheOptions
{
/// <summary>
/// Where to store the cached files and the database
/// Where to store the cached files and the database (directory path)
/// </summary>
public string DiskCacheDirectory { get; set; }
public string CacheLocation { get; set; }

/// <summary>
/// How many RAM bytes to use when writing asynchronously to disk before we switch to writing synchronously.
/// Defaults to 100MiB.
/// </summary>
public long QueueSizeLimitInBytes { get; set; } = 100 * 1024 * 1024;
public long WriteQueueMemoryMb { get; set; } = 100;

/// <summary>
/// Defaults to 1 GiB. Don't set below 9MB or no files will be cached, since 9MB is reserved just for empty directory
/// entries.
/// </summary>
public long CacheSizeLimitInBytes { get; set; } = 1 * 1024 * 1024 * 1024;
public long CacheSizeMb { get; set; } = 1024;

/// <summary>
/// The minimum number of bytes to free when running a cleanup task. Defaults to 1MiB;
/// </summary>
public long MinCleanupBytes { get; set; } = 1 * 1024 * 1024;
public long EvictionSweepSizeMb { get; set; } = 1;

/// <summary>
/// The minimum age of files to delete. Defaults to 10 seconds.
Expand All @@ -40,7 +40,7 @@ public class HybridCacheOptions

public HybridCacheOptions(string cacheDir)
{
DiskCacheDirectory = cacheDir;
CacheLocation = cacheDir;
}
}
}
45 changes: 24 additions & 21 deletions plugins/ImageResizer.Plugins.HybridCache/HybridCachePlugin.cs
Expand Up @@ -53,15 +53,14 @@ private static string GetLegacyDiskCachePhysicalPath(Config config)

private void LoadSettings(Config c)
{
_cacheOptions.DiskCacheDirectory = c.get("hybridCache.cacheLocation", ResolveCacheLocation(_cacheOptions.DiskCacheDirectory));
_cacheOptions.CacheSizeLimitInBytes = c.get("hybridCache.cacheMaxSizeBytes", _cacheOptions.CacheSizeLimitInBytes);
_cacheOptions.DatabaseShards = c.get("hybridCache.shardCount", _cacheOptions.DatabaseShards);
_cacheOptions.QueueSizeLimitInBytes = c.get("hybridCache.writeQueueLimitBytes", _cacheOptions.QueueSizeLimitInBytes);
_cacheOptions.MinCleanupBytes = c.get("hybridCache.minCleanupBytes", _cacheOptions.MinCleanupBytes);
var cacheSizeMb = c.get("hybridCache.cacheSizeMb", _cacheOptions.CacheSizeMb);
var writeQueueMemoryMb = c.get("hybridCache.writeQueueMemoryMb", _cacheOptions.WriteQueueMemoryMb);
var evictionSweepSizeMb = c.get("hybridCache.evictionSweepSizeMb", _cacheOptions.EvictionSweepSizeMb);
var shardCount = c.get("hybridCache.shardCount", _cacheOptions.DatabaseShards);

_cacheOptions.CacheLocation = c.get("hybridCache.cacheLocation", ResolveCacheLocation(_cacheOptions.CacheLocation));
// Resolve cache directory
_cacheOptions.DiskCacheDirectory = ResolveCacheLocation(_cacheOptions.DiskCacheDirectory);

_cacheOptions.CacheLocation = ResolveCacheLocation(_cacheOptions.CacheLocation);

if (FirstInstancePerPath.AddOrUpdate(DiskCacheDirectory, this, (k, v) => v) != this)
{
Expand All @@ -74,7 +73,7 @@ private void LoadSettings(Config c)
}

private string GetDefaultCacheLocation() {
var subfolder = $"imageresizer_cache_{Math.Abs(PathUtils.AppPhysicalPath.GetHashCode())}";
var subfolder = $"imageresizer_cache_{Math.Abs(PathUtils.AppPhysicalPath.GetHashCode()).ToString()}";
return Path.Combine(Path.GetTempPath(), subfolder);
}

Expand Down Expand Up @@ -174,11 +173,11 @@ public async Task ProcessAsync(HttpContext context, IAsyncResponsePlan plan)

private static Imazen.HybridCache.HybridCache CreateHybridCacheFromOptions(HybridCacheOptions options, ILogger logger)
{
var cacheOptions = new Imazen.HybridCache.HybridCacheOptions(options.DiskCacheDirectory)
var cacheOptions = new Imazen.HybridCache.HybridCacheOptions(options.CacheLocation)
{
AsyncCacheOptions = new AsyncCacheOptions()
{
MaxQueuedBytes = Math.Max(0, options.QueueSizeLimitInBytes),
MaxQueuedBytes = Math.Max(0, options.WriteQueueMemoryMb),
WriteSynchronouslyWhenQueueFull = true,
MoveFileOverwriteFunc = (from, to) =>
{
Expand All @@ -188,12 +187,12 @@ private static Imazen.HybridCache.HybridCache CreateHybridCacheFromOptions(Hybri
},
CleanupManagerOptions = new CleanupManagerOptions()
{
MaxCacheBytes = Math.Max(0, options.CacheSizeLimitInBytes),
MinCleanupBytes = Math.Max(0, options.MinCleanupBytes),
MaxCacheBytes = Math.Max(0, options.CacheSizeMb),
MinCleanupBytes = Math.Max(1, options.EvictionSweepSizeMb),
MinAgeToDelete = options.MinAgeToDelete.Ticks > 0 ? options.MinAgeToDelete : TimeSpan.Zero
}
};
var database = new MetaStore(new MetaStoreOptions(options.DiskCacheDirectory)
var database = new MetaStore(new MetaStoreOptions(options.CacheLocation)
{
Shards = Math.Max(1, options.DatabaseShards),
MaxLogFilesPerShard = 3
Expand Down Expand Up @@ -222,7 +221,7 @@ public Task StopAsync(CancellationToken cancellationToken)
return _cache.GetOrCreateBytes(key, dataProviderCallback, cancellationToken, retrieveContentType);
}

private string DiskCacheDirectory => _cacheOptions?.DiskCacheDirectory;
private string DiskCacheDirectory => _cacheOptions?.CacheLocation;


private bool HasNtfsPermission()
Expand Down Expand Up @@ -282,13 +281,17 @@ private DriveInfo GetCacheDrive()
"Please give user " + GetExecutingUser() + " read and write access to directory \"" + DiskCacheDirectory + "\" to correct the problem. You can access NTFS security settings by right-clicking the aforementioned folder and choosing Properties, then Security.", IssueSeverity.ConfigurationError));

//Warn user about setting hashModifiedDate=false in a web garden.
if (_cacheOptions.MinCleanupBytes < 1000 * 1000)
issues.Add(new Issue("HybridCache", "minCleanupBytes should not be set below 1 megabyte (1,000,000). Found in the <hybridCache /> element in Web.config.",
if (_cacheOptions.EvictionSweepSizeMb < 1)
issues.Add(new Issue("HybridCache", "evictionSweepSizeMb should not be set below 1 MB. Found in the <hybridCache /> element in Web.config.",
"Setting a value too low will waste energy and reduce performance", IssueSeverity.ConfigurationError));

if (_cacheOptions.CacheSizeLimitInBytes < 1000 * 1000 * 100)
issues.Add(new Issue("HybridCache", "cacheMaxSizeBytes should not be set below 100 MiB, 1GiB is the suggested minimum . Found in the <hybridCache /> element in Web.config.",
if (_cacheOptions.CacheSizeMb < 100)
issues.Add(new Issue("HybridCache", "cacheSizeMb should not be set below 100 MiB, 1GB is the suggested minimum . Found in the <hybridCache /> element in Web.config.",
"Setting a value too low will increase latency, increase cache misses, waste energy and reduce server performance.", IssueSeverity.ConfigurationError));

if (_cacheOptions.WriteQueueMemoryMb < 50)
issues.Add(new Issue("HybridCache", "writeQueueMemoryMb should not be set below 50 MiB, 100Mib is the suggested minimum . Found in the <hybridCache /> element in Web.config.",
"Setting a value too low will increase latency by forcing images to be written to disk before HTTP responses are sent.", IssueSeverity.ConfigurationError));

if (conflictsExist)
issues.Add(new Issue("HybridCache", "More than one instance of HybridCache has been created for the same directory, these instances will fight.", IssueSeverity.ConfigurationError));
Expand All @@ -304,9 +307,9 @@ private DriveInfo GetCacheDrive()
public IEnumerable<KeyValuePair<string, string>> GetInfoPairs()
{
var list = new List<KeyValuePair<string, string>>();
list.Add(new KeyValuePair<string, string>("hybridCache_" + "cacheMaxSizeBytes", _cacheOptions.CacheSizeLimitInBytes.ToString()));
list.Add(new KeyValuePair<string, string>("hybridCache_" + "writeQueueLimitBytes", _cacheOptions.QueueSizeLimitInBytes.ToString()));
list.Add(new KeyValuePair<string, string>("hybridCache_" + "minCleanupBytes", _cacheOptions.MinCleanupBytes.ToString()));
list.Add(new KeyValuePair<string, string>("hybridCache_" + "cacheSizeMb", _cacheOptions.CacheSizeMb.ToString()));
list.Add(new KeyValuePair<string, string>("hybridCache_" + "writeQueueMemoryMb", _cacheOptions.WriteQueueMemoryMb.ToString()));
list.Add(new KeyValuePair<string, string>("hybridCache_" + "evictionSweepSizeMb", _cacheOptions.EvictionSweepSizeMb.ToString()));
list.Add(new KeyValuePair<string, string>("hybridCache_" + "shardCount", _cacheOptions.DatabaseShards.ToString()));
list.Add(new KeyValuePair<string, string>("hybridCache_network_drive", CacheDriveOnNetwork() ? "1" : "0"));
list.Add(new KeyValuePair<string, string>("hybridCache_filesystem", GetCacheDrive()?.DriveFormat ?? ""));
Expand Down
10 changes: 5 additions & 5 deletions plugins/ImageResizer.Plugins.HybridCache/README_HYBRIDCACHE.md
Expand Up @@ -15,25 +15,25 @@ This plugin only works with the URL API, not the managed API.
1. ` PM> Install-Package ImageResizer.Plugins.HybridCache `
2. In the `<resizer><plugins>` section of `Web.config`, insert `<add name="HybridCache" />`.
3. (optional) In the `<resizer>` section of Web.config, insert <br />
`<hybridCache cacheLocation="C:\imageresizercache\" cacheMaxSizeBytes="1,000,000,000" />`.
`<hybridCache cacheLocation="C:\imageresizercache\" cacheSizeMb="1,000" />`.



## Notes

* `<hybridCache cacheLocation="C:\imageresizercache\"/>` defaults to a app-unique subfolder of the IIS user account's temp folder. Cannot be located in the project or a web-accessible folder.
* `<hybridCache cacheMaxSizeBytes=""1,000,000,000" />` is in bytes and cannot be set below 9MB (9,000,000) or no files will be cached. 1GiB is the suggested minimum.
* `<hybridCache cacheSizeMb="1,000" />` is in bytes and cannot be set below 9MB (9,000,000) or no files will be cached. 1GiB is the suggested minimum.
* `<hybridCache databaseShards="8" />` adjust the number of shards (and write ahead log groups) in the database. Delete the cache folder after changing this number. Don't change this number unless directed by support.
* `<hybridCache queueSizeLimitInBytes="100,000,000" />` limits how much RAM can be used by the asynchronous write queue before making requests wait for caching writing to complete. (HybridCache writes cache entries in the background to improve latency). 100MB is the default and suggested minimum.
* `<hybridCache.minCleanupBytes="1,000,000" />` determines the minimum amount of bytes to evict from the cache once a cleanup is triggered. 1MB is the default and suggested minimum.
* `<hybridCache writeQueueMemoryMb="100" />` limits how much RAM can be used by the asynchronous write queue before making requests wait for caching writing to complete. (HybridCache writes cache entries in the background to improve latency). 100MB is the default and suggested minimum.
* `<hybridCache.evictionSweepSizeMb="1" />` determines the minimum amount of bytes to evict from the cache once a cleanup is triggered. 1MB is the default and suggested minimum.

## Migrating from DiskCache or TinyCache

* **Delete your `/imagecache/` folder (otherwise it will become publicly accessible!!!)** (Actually, if installed, HybridCache will kill the application with an error message to prevent that - for all we know you resize images of passwords and have directory listing enabled)
* Delete references to `DiskCache` and `TinyCache` from **both nuget.config and Web.config**
* `Install-Package ImageResizer.Plugins.HybridCache`
* Put `<add name="HybridCache" />` in the `<resizer><plugins>` section of `Web.config`
* Put `<hybridCache cacheLocation="C:\imageresizercache\" cacheMaxSizeBytes="1,000,000,000" />` in the `<resizer>` section of `Web.config`. If you want to use a temp folder, omit cacheLocation.
* Put `<hybridCache cacheLocation="C:\imageresizercache\" cacheSizeMb="1,000" />` in the `<resizer>` section of `Web.config`. If you want to use a temp folder, omit cacheLocation.
* HybridCache requires a cache folder outside of the web root. DiskCache did not support that.
* HybridCache, unlike DiskCache, can precisely limit the cache size & disk utilization.
* HybridCache uses a write-ahead log to prevent orphaned cache entries.
Expand Down
1 change: 1 addition & 0 deletions tests/ImageResizer.AllPlugins.Tests/TestAll.cs
Expand Up @@ -114,6 +114,7 @@ public static Config GetConfig()
public static List<object> GetSourceObjects()
{
var sources = new List<object>();
//TODO: This breaks!
sources.Add(@"C:\Users\lilith\work\resizer\examples\images\red-leaf.jpg");
//sources.Add("~/images/red-leaf.jpg");
// sources.Add("/gradient.png");
Expand Down
8 changes: 4 additions & 4 deletions tests/api-surface/ImageResizer.Plugins.HybridCache.txt
Expand Up @@ -7,12 +7,12 @@ namespace ImageResizer.Plugins.HybridCache
public class HybridCacheOptions
{
public HybridCacheOptions(string cacheDir) { }
public long CacheSizeLimitInBytes { get; set; }
public string CacheLocation { get; set; }
public long CacheSizeMb { get; set; }
public int DatabaseShards { get; set; }
public string DiskCacheDirectory { get; set; }
public long EvictionSweepSizeMb { get; set; }
public System.TimeSpan MinAgeToDelete { get; set; }
public long MinCleanupBytes { get; set; }
public long QueueSizeLimitInBytes { get; set; }
public long WriteQueueMemoryMb { get; set; }
}
public class HybridCachePlugin : ImageResizer.Plugins.IAsyncTyrantCache, ImageResizer.Plugins.IPlugin, ImageResizer.Plugins.IPluginInfo, ImageResizer.Plugins.IPluginRequiresShutdown
{
Expand Down
1 change: 1 addition & 0 deletions tests/api-surface/ImageResizer.txt
Expand Up @@ -622,6 +622,7 @@ namespace ImageResizer.Configuration
public void WriteDiagnosticsTo(string path) { }
public bool get(string selector, bool defaultValue) { }
public int get(string selector, int defaultValue) { }
public long get(string selector, long defaultValue) { }
public string get(string selector, string defaultValue) { }
public T get<T>(string selector, T defaultValue)
where T : struct, System.IConvertible { }
Expand Down

0 comments on commit da51052

Please sign in to comment.