Code Monkey home page Code Monkey logo

glav.cacheadapter's Introduction

Build Status

Glav.CacheAdapter - README

This library allows developers to code against a single interface ICacheProvider and be able to run against a variety of cache implementations simply by changing configuration values. The currently supported list of cache engine/implementations are:

Note that this is only a brief introduction to the CacheAdapter, however for more detailed information, see the related blog posts listed below.

How do I get set up?

  • Nuget

Easiest way is to install the full nuget package into a simple console app, delete the 'program.cs' file that gets added by default, then run the app. You can see the example code at work.

  • Download/Clone and play

You can download or clone this repository, then have a look at the example code provided.

  • A bit more details on getting setup Modify your app.config/web.config to contain what cache to use.
 <appSetttings>
  <add key="Cache.CacheToUse" value="memory" />
  <add key="Cache.IsCacheEnabled" value="true" />
  <add key="Cache.IsCacheDependencyManagementEnabled" value="true" />
  <add key="Cache.CacheSpecificData" value="" />
  <add key="Cache.LoggingLevel" value="Information"/>
 </appSetttings>

This configuration will use the memory cache for all operations, enabled dependency management (parent/child key relationships - see below), and logs all information and errors.

Then, in code you can do:

  var data1 = AppServices.Cache.Get<string>("cache-key", DateTime.Now.AddSeconds(5), () =>
  {
    return "Some data from a data store";
  });

which will return the data from cache if it exists in the cache, or use the lambda function to retrieve the data, add it to the cache , then return it for you. The data will remain in the cache for 5 seconds.

Blog Posts

  • Version 2.0 has details on memcached support.
  • Version 3.0 has details on Cache dependency management features.
  • Version 3.2 has details on package structure changes.
  • Version 4.0 has details on redis support.
  • Version 4.1 has async methods, configurable logging and targets the .Net framework 4.5.
  • Version 4.2/4.2.1 has a licence file, config bug fix and fluent configuration.

Who do I talk to?

  • Paul Glavich (Owner). I can be contacted via twitter ( @glav ), or through the issue register within this repository.

Revision History

Version 4.3

  • Update runtime to 4.7.2
  • Added support to specify user and password for memcached cache to support MemcachedCloud (Redislabs). See PR here
  • Some cleanup

Version 4.2.2

  • Spelling changes and readme file fixes.

Version 4.2.0/4.2.1

  • Note: 4.2.1 was a simple package bug fix. No code changes.
  • Added a licence file - Issue 49
  • Overhauled internals to provide better structured factory creation of cache engines and dependencies.
  • As a result of the overhaul above, provide a fluent configuration ability to configure the cache from code much easier Issue 50. This also fixes a multiple config instance issue Issue 40
using Glav.CacheAdapter.Helpers;

var provider = CacheConfig.Create()
                .UseMemcachedCache()
                .UsingDistributedServerNode("127.0.0.1")
                .BuildCacheProviderWithTraceLogging();
  • Breaking change: There was previously 2 ways of expressing configuration in the configuration file. In addition, due to a configuration system overhaul, this has now been changed to support only one. Specifically, the configuration section option has been removed and now only the method of configuration is supported. So if you had something like:
<applicationSettings>
        <Glav.CacheAdapter.MainConfig>
            <setting name="CacheToUse" serializeAs="String">
                <value>memcached</value>
            </setting>
            <setting name="DistributedCacheServers" serializeAs="String">
                <value>localhost:11211</value>
            </setting>
        </Glav.CacheAdapter.MainConfig>
</applicationSettings>

That should now be changed to:

<appSettings>
  <add key="Cache.CacheToUse" value="memcached" />
  <add key="Cache.DistributedCacheServers" value="localhost:11211" />
</appSettings>

Version 4.1.1

  • Version 4.1.1 in Nuget is simply a revision of the packaging. Glav.CacheAdapter.Core package 4.1.1 only contains the assembly. Glav.CacheAdaper 4.1.1 simply references the 4.1.1 core package. There has been no assembly change. In both packages, the assembly version is 4.1.0.

Version 4.1.0

  • Allow control of logging detail via <add key="Cache.LoggingLevel" value="Information|ErrorsOnly|None"/> - Issue 43
  • Addition of Async methods on the cache provider interface. Issue 27
  • Updated nuspec target framework to expect .Net 4.5 as a minimum to reduce dependencies. Issue 42

Version 4.0.1

  • Fixed minor typo is naming of RedisCacheAdapter (was misspelled RedisCacheAdatper) - Issue 34

Notes on Version 4.0

  • Added support for cache type of redis <add key="Cache.CacheToUse" value="redis"/>
  • Also adds support for a redis specific dependency manager which is more efficient than the default for redis <add key="Cache.DependencyManagerToUse" value="redis"/> *Note: using <add key="Cache.DependencyManagerToUse" value="default"/> will default to using the redis specific cache dependency manager if the redis cache engine is selected. You can override this to use the generic dependency managment engine by using: <add key="Cache.DependencyManagerToUse" value="generic"/>
  • Fix for minor performance issue when checking the dependency management (Issue 33)
  • Addition of an extra method on the ICache/ICacheProvider interface - InvalidateCacheItems - to allow efficient batch deletions/removals of cache items.
  • Much more efficient DependencyManager (both generic and redis specific) to remove large lists of dependencies quicker.
  • Fixed a bug where a new config was not properly applied, if applied after initial initialisation.

Version 3.2.1

  • Fix for Issue 29. Using SecurityMode=None incorrectly depended on SecurityMessageAuthorizationKey setting. This is now resolved.

Version 3.1 and also 3.2 (combined)

  • Support for SecurityMode.None for AppAfabric caching (Issue 20)
  • Support for LocalCaching configuration values (Issue 21)
  • For local caching support, you can specify the following in the cache specific data: <add key="Cache.CacheSpecificData" value="LocalCache.IsEnabled=true;LocalCache.DefaultTimeout=300;LocalCache.ObjectCount;LocalCache.InvalidationPolicy={TimeoutBased|NotificationBased}"/> Note: DefaultTimeout value specifies amount of time in seconds.
  • Support for programmatically setting the configuration and initialising the cache. (Issue 19)
  • Splitting Glav.CacheAdapter package into 2 packages - Glav.CacheAdapter.Core & Glav.CacheAdapter. (Issue 13)
  • The "Core" package contains just the Glav.CacheAdapter assembly and references to dependencies so it is much easier to update the package and NOT include the readme and example code all the time.
  • Merged in changes from Darren Boon's cache optimisation to ensure data only added to cache when its enabled and non null. Involved code cleanup as this branch had been partially merged prior.
  • Merged change from https://bitbucket.org/c0dem0nkee/cacheadapter/branch/default to destroy cache when using local cache on calling ClearAll method.

Version 3.0.3

  • Minor bug fix to memcached dependency management. Would not store dependencies when trying to store master cache dependency list for longer than 25 years.

Version 3.0.2

  • Fixes to readme.txt and instructions

Version 3.0.1

  • Minor bug fix when using appfabric and NOT including the CacheSpecificData section. Would throw an error as default of this (if not present) contains an invalid example security key. Supply some CacheSpecificData would resolve this but this update fixes that.

Notes on Version 3.0

  • New Feature: Addition of new Cache Dependency Feature to provide initial support to associate cache items to other cache items so that when one is invalidated, all related items are automatically invalidated.
  • Modification to configuration system to support storing configuration overrides for all settings in the <appSettings> element in config.
  • New API Feature: Support for clearing the cache programmatically. You can now call the ClearAll API method to clear the entire contents of the cache programmatically.
  • Support of ChannelOpenTimeout and MaxConnectionsToServer configuration value for Windows Azure and Appfabric caching (in seconds). The ChannelOpenTimeout value allows easier debugging when having connection issues as sometimes the client can forcibly disconnect early and not get an valid exception. Setting this value to much higher allows the client to wait longer for a valid error from the server. An example which sets the ChannelOpenTimeout to 2 minutes(120 seconds) is: <add key="Cache.CacheSpecificData" value="UseSsl=false;ChannelOpenTimeout=120;SecurityMode=Message;MessageSecurityAuthorizationInfo={your_security_token}"/>
  • MaxConnectionsToServer allows fine tuning performance for the number of concurrent connections to the cache service. Currently, the Azure client defaults to 1.
  • Supports an ICacheFeatureSupport interface and base implementation. This is provided as a property on the ICacheProvider allowing basic feature detection. Currently this only supports identifying if a cache can be cleared but this will be expanded in the future.eg. cacheProvider.FeatureSupport.SupportsClearingCacheContents()
  • Modifying configuration to support storing values in AppSettings section using "Cache." as keyprefix. This means you can use the same named config settings in <appSettings> section(or in a separate appSettings file) as long as you prefix the appSetting with 'Cache.' For example, normally the main config section has:
<Glav.CacheAdapter.MainConfig>
      <setting name="CacheToUse" serializeAs="String">
        <value>memcached</value>
      </setting>
</Glav.CacheAdapter.MainConfig>

in the appSettings, you could override this by having:

<appSettings>
      <add key="Cache.CacheToUse" value="memory"/>
</appSettings>
  • In other words, you no longer need a <Glav.CacheAdapter.MainConfig> section. You can use the <appSettings> section only if you choose.In fact, the <appSettings> approach is the preferred method.

######CacheDependencyManagement Details######

  • Feature Addition: Rudimentary support of CacheDependencies. Note: Enabling this feature when using the default dependency support, incurs some performance hit due to more calls being made to the caching engine. This can result in a more "chatty" interface to the cache engine,and higher cache usage, therefore more memory and connections to the cache.
  • This feature (and all advanced features) are only available when using the ICacheProvider interface implementation. This is by design. The ICache abstraction is a raw abstraction over the basic cache engine.
  • Includes a generic cache dependency mechanism which acts as a common base. Not the most efficient but intent is to later introduce cache dependency managers which utilise specific features of the cache engine to maximise performance.
  • The cache dependency implementation works as a parent/child mechanism. You can register or associate one or more child cache keys to a parent item. The cache key can actually be the key of an item in the cache but it doesn't have to be. So the parent key can be an arbitrary name or the key of an item in the cache.If it is an item in the cache, it will get invalidated when instructed as normal. Additionally, a child key of a parent key, can itself act as the parent for other cache keys. When the top level parent is invalidated, all its dependent children, and any further nested dependent children will also be invalidated. For example:
    // Gets some data from main store and implicitly adds it to cache with key 'ParentKey'
    cacheProvider.Get<string>("ParentKey",DateTime.Now.AddDays(1),() => "Data");
	// Gets some data from main store and implicitly adds it to cache with key 'FirstChildKey' 
	// and as a dependency to parent item with key "ParentKey"
    cacheProvider.Get<string>("FirstChildKey",DateTime.Now.AddDays(1),() => "Data","ParentKey");
	// Gets some data from main store and implicitly adds it to cache with key 'ChildOfFirstChildKey' 
	// and as a dependency to parent item with key "FirstChildKey" which itself is a dependency to item with key "ParentKey"
    cacheProvider.Get<string>("ChildOfFirstChildKey",DateTime.Now.AddDays(1),() => "FirstChildKey");

	// At this point, the cache item relationship looks like
	// ParentKey
	//    +-----> FirstChildKey
	//                   +-------> ChildOfFirstChildKey

	// Invalidate the top level Parent, which clears all depenedent keys, included nested items
	cacheProvider.InvalidateCacheItem("ParentKey");
  • Note: A Parent can have a child key(s) that are themselves parents of the top level key causing recursion. This is fully supported by the code and no infinite loops are created. All relevant cache keys are cleared/actioned as normal within the collective set of dependent keys.

Version 2.5.3

  • Fixed bug where setting minpool size and max pool size resulted in an error when minpoolsize > default max pool size of 20.
  • Rewrite of adding per request cache dependency. Always uses web cache for this purpose if available, otherwise does nothing.

Notes on Version 2.5

  • This version takes a dependency upon enyim memcached. The reason is simply performance. I was doing a lot of performance work only to realise I was duplicating work already tried and tested in Enyim memcached caching component so have taken a dependency on that. This release is again only has changes related to memcached. The performance of enyim memcached is fantastic so you you should see some really good gains.
  • If you need more information, please look at the following blog posts: Caching Architecture–Testability, Dependency Injection and Multiple Providers CacheAdapter now a Nuget package

glav.cacheadapter's People

Contributors

ferventcoder avatar glav avatar katrash avatar pdgerads avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

glav.cacheadapter's Issues

How to check if Redis connection is established

I'm trying to set up Redis caching with the following configuration:

    <add key="Cache.CacheToUse" value="redis" />
    <add key="Cache.IsCacheEnabled" value="true" />
    <add key="Cache.CacheDurationInSeconds" value="300" />    
    <add key="Cache.LoggingLevel" value="Information"/>
    <add key="Cache.DistributedCacheServers" value="sample.redis.cache.windows.net:6379" />
    <add key="Cache.CacheSpecificData" value="ssl=false;abortConnect=false;connecttimeout=15000;password={mypass}" />

When I then call AppServices.Cache.GetAsync() with lambda, my lambda is being called all the time, as there is no cache. If I change server name, or pass - nothing is changed, no exception, error or timeout. And if I then go to Azure Redis CLI and type "GET {mycachekey}", then {nil} is returned.

So I'm not sure whether my app is really connected to Azure Redis or not. How can I check it?

Fix Add to Overwrite existing Cache item

There is a different between Add and Set within System.Runtime.Caching

Add does nothing if the cache key already exists.

I suggest either creating a similar function for this library or change the behaviour of Add so that it overwrites the value all times.

Often you will want to update the value manually after its already loaded (after a action) and decaching causes the method to run the logic again duplicating the effort.

Note: Copied from old bitbucket repo

How to - Use Memcached with MemcachedCloud (RedisLabs) that requires user/pass

There is this nice article out there (https://redislabs.com/memcached-appharbor), but I don't know how to give username and password specifically to Cache.CacheSpecificData. How does one do that?

I'd prefer not to pull out Glav.CacheAdapter and go straight to Enyim to get SASL functionality.

Originally reported by @ferventcoder on Bitbucket at https://bitbucket.org/glav/cacheadapter/issues/39/how-to-use-memcached-with-memcachedcloud

Issue with CreatePackage.cmd script(s)

As mentioned in this comment here:

#3 (comment)

There seems to be a small issue with the CreatePackage.cmd script. When I ran this on my local machine, after building in Release mode in Visual Studio, I got the following output:

image

The problem here being that the lib\net472 folder doesn't exist, so the copy command isn't able to complete.

There are multiple ways that this "could" be fixed, so I won't create a PR for it, as I don't know how you would like to move forward with addressing it. If you let me know how you want to proceed, I would be happy to submit a PR, so that we can get a new release pushed to NuGet.org.

Separated NuGet packages per cache provider

It would be nice to have a separated package per cache provider, so for instance:

  • CacheAdapter.AppFabricCache
  • CacheAdapter.Memcached

In this way every NuGet package take dependency only on the technology it needs, AppFabric will only take dependency on CacheAdapter.Core and ServerAppFabric.Client.
Probably the Memory and Web implementation could be integrated in the CacheAdapter.Core because it only relies on .NET framework.
CacheManager is making something similar CacheManager.AppFabricCache

Also from Todd Carter
I agree with Michael - I really do not want to install 3-4 additional packages which I do not use and then get deployed. There should be a core with memory only and then a CacheAdapter.Redis CacheAdapter.AppFabric etc packages. I am not aware of anyone whom would choose to use multiple adapters in the same project so why deploy them all at once. To me this is not minor and in fact is blocking our using this package.

This issue has been migrated from the original bitbucket issue#32 on 13-09-2017

System.Xml.XmlException, Xml_BadStartNameChar 0x3C can not start with char '<' for method name

I get this exception when I try this :
return GlavCacheManagement.GetCache("cachekey",15, () => { var list= _repo.GetByLang(IsActiveOrAccepted.Active); return (currentLangId> 0 ? list.Where(x => x.LangId== currentLangId) : list).ToList(); });

My GlavCacheManagement class method
public static T GetCache<T>(string key, int h, Func<T> del) where T:class { if (FrSettings.Settings.IsGlavCacheActive) { return AppServices.Cache.Get<T>(key, DateTime.Now.AddMinutes(h),del); } return del.Invoke(); }

My delegate name is the problem here is the delegate info

FullName : Sport.DataAccess.Services.UserDestekHedefServices+<>c__DisplayClass9_0.<GetActiveHedefOfUser>b__0()

Name : <GetActiveHedefOfUser>b__0

Stacktrace: konum: System.Xml.XmlConvert.VerifyNCName(String name, ExceptionType exceptionType)

How to know the size of the cached item?

I'm trying to figure out the size of my caching items. Is there an easy way to get this information?

Also from user: "Anshul Mehta" -> Is there any update on this issue ? I am trying to figure out the size of the cached items ,my concern is I am using cache object to store data associated for localization related to labels .The issue is while using appdynamics tool ,we figured out that translation calls are taking the max time as it is used in a loop but since we are fetching data from cache it should not . Now my current implementation is using in memory cache and caching data for different tables using keys. Can I create a 2 separate cache objects using 2 different keys ?

Originally reported by @ferventcoder on Bitbutcket at https://bitbucket.org/glav/cacheadapter/issues/41/how-to-know-the-size-of-the-cached-item

Support protobuf serialization

Hi all,
When caching large amounts of data, the serializer used plays an important role. Protobuf is currently faster than all .NET-provided serializer
Since the Enym memcache client already supports protobuf serializer through protobuf-net.Enyim NuGet package, it would be great to extend this support to the rest of the caching mechanisms provided by CacheAdapter.
I would definately like to be able to change the serializers in the config file (from Binary to Xml to Protobuf and so on).
Let me know your thoughts on this.
Thanks, Simo

RedisDependencyManager doesn't handle redis not being available

Using version 4.1.1 ,if the redis server isn't running or can't be connected to, the call to _redisDatabase.KeyExists() in RegisterParentDependencyDefinition() throws an exception.
My config is as follows:
It looks like the method: Get(string cacheKey, DateTime absoluteExpiryDate, Func getData, string parentKey = null, CacheDependencyAction actionForDependency = CacheDependencyAction.ClearDependentItems) handles the cache not being available when checking for the item, it's the code that tries to update the dependencies that doesn't.

After playing with this some more, I think there are two situations to consider:

  1. redis is not available when the application starts (or is recycled)
  2. redis is temporarily unavailable while the application is running

Event 2 is more likely to occur and I don't want it to make my app throw an exception. When reading, it should treat it as if it's not cached. An error when writing is trickier - perhaps only this web app can't connect, and others are fine? What if this is a dependency clear - other apps may still be able to get old data from redis.

Issue raised by @pdonovan on Bitbucket 2016-04-19 and migrated to Github

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.