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

[Proposal] A non-destructive way to support AzureBlobCache settings customisation #432

Closed
Philo opened this issue Jul 15, 2016 · 5 comments
Closed

Comments

@Philo
Copy link
Contributor

@Philo Philo commented Jul 15, 2016

We've previously discussed (#369) the ability to support customisation of the settings values for the ImageCacheBase and specifically the AzureBlobCache.

At present all configuration logic happens within the constructor, whether the Settings dictionary to read and applied to internal properties, this method prevents any derived implementations from altering those base settings before they are applied.

From our previous discussion you were not inclined to make any significant changes the ImageProcessor as you were starting on Core support, I can totally understand and accept that, I do however have a proposal for a minor change that will allow for the AzureBlobCache and ImageCacheBase to support a customisation path for the scenario where you want to store configuration details elsewhere.

My proposal is to introduce a means to augment the ImageCacheBase with two new methods:

private void AugmentSettingsCore(Dictionary<string, string> settings)
{
  AugmentSettings(settings);
}

protected virtual void AugmentSettings(Dictionary<string, string> settings)
{
}

Then call AugmentSettingsCore(Settings) from the ImageCacheBase constructor:

protected ImageCacheBase(string requestPath, string fullPath, string querystring)
{
  this.RequestPath = requestPath;
  this.FullPath = fullPath;
  this.Querystring = querystring;
  this.Settings = ImageProcessorConfiguration.Instance.ImageCacheSettings;
  this.MaxDays = ImageProcessorConfiguration.Instance.ImageCacheMaxDays;
  this.BrowserMaxDays = ImageProcessorConfiguration.Instance.BrowserCacheMaxDays;
  AugmentSettingsCore(Settings);
}

This will allow a derived instance to act on the settings before the immediate classes (like AzureBlobCache) and then allow the Settings values to be updated via custom logic.

Here is my working example (that has required me to re-implement the AzureBlobCache locally):

<appSettings>
  <add key="AzureBlobCache.CachedStorageAccount" value="<storage connection string>" />
  <add key="AzureBlobCache.CachedCDNRoot" value="https://somewhere.com" />
  <add key="AzureBlobCache.SourceStorageAccount" value="<storage connection string>" />
</appSettings>

<caching currentCache="AzureBlobCache">
  <caches>
    <cache name="AzureBlobCache" type="Test.AzureBlobCacheFromAppSettings, Test" maxDays="365" />
  </caches>
</caching>

Which is read by:

public class AzureBlobCacheFromAppSettings : AzureBlobCache
{
    public AzureBlobCacheFromAppSettings(string requestPath, string fullPath, string querystring) : base(requestPath, fullPath, querystring)
    {
    }

    protected override void Configure(Dictionary<string, string> settings)
    {
        var prefix = $"{nameof(AzureBlobCache)}.";
        var removePrefix = new Func<string, string>(key => key.Replace(prefix, string.Empty));

        var matchingKeys = ConfigurationManager.AppSettings.AllKeys.Where(
            key => key.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase));
        matchingKeys.ForEach(key =>
        {
            settings.AddOrUpdate(removePrefix(key), key.FromAppSettings());
        });
    }
}

Which derives from (updated from AzureCacheBlob.cs)

public AzureBlobCache(string requestPath, string fullPath, string querystring)
    : base(requestPath, fullPath, querystring)
{
    ConfigureCore(Settings);
    // Retrieve storage accounts from connection string.
    CloudStorageAccount cloudCachedStorageAccount = CloudStorageAccount.Parse(this.Settings["CachedStorageAccount"]);

    // Create the blob clients.
    CloudBlobClient cloudCachedBlobClient = cloudCachedStorageAccount.CreateCloudBlobClient();

    // Removed for brevity...
}

private void ConfigureCore(Dictionary<string, string> settings)
{
    Configure(settings);
}

protected virtual void Configure(Dictionary<string, string> settings)
{
}

This change would allow the sensitive configuration values such as storage account connection strings and other environment specific settings to be managed based on the requirements of the application/developer.

Apologies for the wall of text :)

@JimBobSquarePants

This comment has been minimized.

Copy link
Owner

@JimBobSquarePants JimBobSquarePants commented Jul 15, 2016

@Philo Well done!! 💯

I really like this, especially how you avoided having to touch the interface. If you want to open a PR with the code changes I would be more than happy to accept them.

I really appreciate the effort you have made.

Cheers

James

@JimBobSquarePants

This comment has been minimized.

Copy link
Owner

@JimBobSquarePants JimBobSquarePants commented Aug 3, 2016

@Philo That's the code released now. Thanks again for your PR, a really excellent way to work around the limitations of my API. 👍

@erzki

This comment has been minimized.

Copy link

@erzki erzki commented Jun 30, 2017

Are there any documentation of how to use this which as I understand is in the latest release?

@CasperTDK

This comment has been minimized.

Copy link

@CasperTDK CasperTDK commented Jul 28, 2017

Really nice, but do we not have the same issue for CloudImageService?

@aerionTech

This comment has been minimized.

Copy link

@aerionTech aerionTech commented Oct 18, 2018

Thanks for the great solution and getting this implemented.
I have written up a blog post on our company blog about how this was implemented and we use it with multiple AppService Slots

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.