We have this 90.000 lines Json object that takes 5 seconds to load. We need to load all this data since there is a lot of relations that needs to be included. Fortunately this data almost never change so it will basically always be the same (it do need to be able to snap out of the cache if the data updates)
Im not that good on server side cache so my question is.
If i cache this serverside i guess all users will be served the cached answer until the cache releases?
Can i cache this response on the server for until i somehow tell the api stop caching this? Its fine to hold 24 hours cache
Any libriaries that i can achieve this with?
Regards
You could use MemoryCache in .Net Framework
MemoryCache lives in the Process, so all users can access the same cached data if you want (on the same server)
You set the expiration time when saving to the cache.
Built in the Framework
Thanks for the input my first attempt looks like this. It seems to work. Please provide feedback
MemoryCache memoryCache = MemoryCache.Default;
var test = memoryCache.Get("testKey")
if (test != null) {
return Ok(test)
} else {
var data = GetData()
.ToList();
memoryCache.Add("testKey", data, DateTimeOffset.UtcNow.AddDays(1));
return Ok(data)
}
Related
We are storing a serialized object in to Redis cache. We want to check the age of cache before retrieving new data and update the cache. If it is less than 10 mins, as data might not have changed in that duration, so we pull from cache and send to API output. if not, we will still return cached data to output, request new pull of data, update cache if new data is available and intimate the web listener to get latest update.
Is there a way with existing cache API, that we can check the age of Redis cache key? If no, any workarounds?
I think you're looking at it from the wrong perspective.
What would happen if you were to use Redis' EXPIRE with a TTL of 10min for each of your cache's keys? Redis will keep the data for 10min and then expire it, simplifying the application's logic. You would no longer need to actively check the "age" of the key - if it isn't in Redis then you need to fetch (for reference look up the so-called "Cache Aside" pattern).
Is it possible to cache once produced response on server-side and then redeliver it in response to the same request?
Let me explain:
I have an endloint that takes about 5 seconds to generate a response - this includes going to the database and fetching data, processing it, performing some computations on it, serealizing and gzipping the response - the entire thing takes 5 seconds.
Once this is done for the first time I want the result to be available for all the requests coming from all the users.
In my views client side caching, when you either cache the result on the client and do not hit the server at all for some time or when you hit the server but get 304 not-changed instead of the data is not good enough.
What i want is to hit the sever and if this enndpoint (with the same set of parameters) was already called by anyone then get the full response. Is it possible at all?
You have a number of options for this.
One option is API level caching, you create a key using the parameters required to generate the response, you go and fetch the data and save the pair in the cache. Then next time a request comes in, you recreate the key and go and check your cache first. If it's there, happy days, return it, if not, go fetch it and store it.
This of course depends on the amount of data you have, too muchm data or too big data and this will not work. You could also store it for a while, say 10 minutes, 1 hour etc.
If you have a lot of data and caching like this isn't possible then consider something else. Maybe create your own no-sql cache store ( using something like MongoDB maybe ),store it and retrieve it from there, without the need for any changes so it's a straight retrieve, thus very quick.
You could also use something like Redis Cache.
Lots of options, just choose whatever is appropriate.
I have implemented REST service using WebAPI2, service implemeted to manage different sessions which are created and joined by different clients which are accessing service.
Session contains information about access of application functionality and information of participants which have joined same session.
Each client get session information and access list from server for synchronization purpose on every second. According to access changed, client functionality will changed(Enable/Disable).
I am using MemoryCache class to store session info in WebAPI service as below.
public static class SessionManager{
private static object objForLock = new object();
public static List<Session> SessionCollection
{
get
{
lock (objForLock)
{
MemoryCache memoryCache = MemoryCache.Default;
return memoryCache.Get("SessionCollection") as List<Session>;
// return HttpContext.Current.Application["SessionCollection"] as List<Session>;
}
}
set
{
lock (objForLock)
{
MemoryCache memoryCache = MemoryCache.Default;
memoryCache.Add("SessionCollection", value, DateTimeOffset.UtcNow.AddHours(5));
//HttpContext.Current.Application["SessionCollection"] = value;
}
}
}
}
My problem is regarding inconsistent behavior of cache.
When clients send synchronization call, it will gives inconsistent results. For some requests, clients gets proper data and for some requests client gets null data alternative after some requests.
I have add debugger and monitor the object for null result, then "memoryCache.Get("SessionCollection")" also null. After some consecutive request it will be proper again. I am not getting why this object is not persistent.
Alternative, I have tried "HttpContext.Current.Application["SessionCollection"]" as well, But same issue is there.
I have read about "app pool recycle", it recycle all cache after particulate time. If my cached object is recycled by app pool recycle, then how can I get this object again?
Please some can help me to get out of this issue. Thanks in advance.
You should store client specific information in Session instead of Cache. Cache should be for the whole application (shared)
However, it's not recommended as web api is built with RESTful in mind and RESTful services should be stateless (APIs do not cache state). Stateless applications have many benefits:
Reduce Memory Usage
Better scalability: Your application scales better. Image what happens if you store information of millions of client at the same time.
Better in load balancing scenario: every server can handle every client without losing state.
Session expiration problem.
In case you want to store client state, you could do it anyway. Please try the suggestions in the following post: ASP.NET Web API session or something?
In general, caching state locally on the web server is bad (both Session and local MemoryCache). The cache could lose for many reasons:
App pool recycle.
Load balancing environment
Multiple worker processes in IIS
Regarding your requirements:
Each client get session information and access list from server for
synchronization purpose on every second. According to access changed,
client functionality will changed(Enable/Disable).
I'm not sure if you want to update the other clients with new access list immediately when a client sends synchronization call. If that's the case, SignalR would be a better choice.
Otherwise, you could just store the updated access list somewhere (shared cache or even in database) and update the other clients whenever they reconnect with another request.
#ScottHanselman said about a bug in .NET 4 here. I hope this fix help you:
The temporary fix:
Create memory cache instance under disabled execution context flow
using (ExecutionContext.SuppressFlow()) {
// Create memory cache instance under disabled execution context flow
return new YourCacheThing.GeneralMemoryCache(…);
}
The Hotfix is http://support.microsoft.com/kb/2828843 and you can request it here: https://support.microsoft.com/contactus/emailcontact.aspx?scid=sw;%5BLN%5D;1422
Just a caution, MemoryCache will keep data in memory in single server. So if you have multiple web servers(in front of load balancers), that cache will not be available to other servers. You also use the cache name - "SessionCollection". That data will be shared to all clients. If you need to store data in cache unique to each client, you need to return a token (guid) to the client and use that token to get/update data in cache in subsequent requests.
Try introducing a class level variable. So your code will look like below. (Some code remove for clarity)
private readonly MemoryCache _memCache = MemoryCache.Default;
....
return _memCache.Get("SessionCollection") as List<Session>;
...
_memCache .Add("SessionCollection", value, DateTimeOffset.UtcNow.AddHours(5));
I have a custom centralized MemoryCache and wrapper to be exposed over network. The objects to be stored are expected to be large and accessed frequently. The network traffic might become a bottleneck just because of the size of the data.
So, I want to return some kind of value that the clients may ask first to check if they need a new value from the cache server. I have 3 options:
Generate checksum in the cache server and return to client while adding object to cache.
Generate
Get current time tick in the cache server and return to client while adding object to cache.
In both the cases, the checksum or time tick will also be added in cache with different key so that clients may query it separately.
I can avoid this if either of these values is available from MemoryCache directly. Any idea?
Thanks in advance.
I am creating a graphical tool in silverlight which reads data from multiple files and database.
i dont want to call the database again and again. i want to retrieve the data when required and keep it safe somewhere so if the user or any other user visits the same page, they can then access the data.
i want to use application state of asp.net Cache["Object"] but in Silverlight? what is the best methodolgy?
Since silverlight is running client side you need to cache serverside.
You could fetch your data with WCF.
Something along these lines:
What I have done in the past is to cache the query using a WCF using enterprise library:
public class YourWcfService
{
ICacheManager _cacheManager = null;
public YourWcfService()
{
_cacheManager = EnterpriseLibraryContainer.Current.GetInstance<ICacheManager>("Cache Manager");
}
}
your web method would look something like:
[OperationContract]
public List<Guid> SomeWebMethod()
{
if (_cacheManager.Contains("rgal")) // data in cache?
result = (List<Guid>)_cacheManager.GetData("rgal");
if (result == null)
{
result = FETCH FROM DATABASE HERE;
// cache for 120 minutes
_cacheManager.Add("rgal", result, CacheItemPriority.Normal, null, new AbsoluteTime(TimeSpan.FromMinutes(120)));
}
return result;
}
Silverlight controls run in browser/client side per user, so caching something for all users on the server is not possible.
You can cache data in the control for given user's session or in isolated storage for given user. But you can't do anything on the server without writing corresponding server side code.
Is the caching really necessary? Are you really pounding your database that bad?
Your DB is your storage. Unless you have a performance issue, this is premature optimization.
The new Enterprise Library Silverlight Integration Pack provides you with capabilities of caching on the client. 2 types of data caching are supported: in-memory and to isolated storage. You'll also get flexibility of configuration of the expiration policies (programmatically or via external config) and a config tool support.
Note: it's a code preview now, but should be releasing as final in May.