Purge varnish cache based on request header values - varnish

I am caching multiple copies of an object based on certain header values in the request using vcl hash. How do I purge them all at once?

My answer is based on assumption that you really want to purge as in PURGEand not BAN:
In case all the possible values of the certain header are known, you would use restarts coupled with setting custom header. Logic is the following:
received PURGE request for object with req.http.X-Custom == foo
return(purge)
in vcl_purge, set req.http.X-Custom = bar, and introduce / adjust helper header with the set of values already purged, and return (restart)
As a result, Varnish will recursively purge all the objects.
You can see example of this approach in complete Brotli VCL implementation.
But in case the values of the certain header are really arbitrary, you can't really PURGE them all at once. If you need this, you have to make use of Vary: X-Custom so that Varnish will consider all those objects as one with many variations. With Vary in place, you don't have to hash on the header and PURGE on one variation will effectively clear out all other variations.
I like Vary approach much better.

Related

Concurrency editing or locking cells in Excel with REST-APIs

I'm working on a web application as a front end for an Excel Sheet. The REST-APIs seems to be quiet clear. But I am not sure how to handle concurrency correctly. I want to avoid that two clients accidentally override their data. I need some kind of primary key which could be edited in worst case by two users. What is the correct way to handle that with the Microsoft Graph?
Right now I have in mind to do some kind of double locking so that I allocate a key and check then if it was overwritten after a second. But that seems to be quiet hacky and I'm sure that there is a way to lock cells so that two users cannot edit the same cells.
Normally you do this with ETag and update only when the If-Match header is verified. When somebody changes the resource, then the ETag changes and the old ETag won't match any longer. There can be still a short period of time when the ETag is the old for both requests, so there is no perfect solution.
In the case of MS Graph API I see an "#odata.etag" property for the resource and the sub-resources, so I assume they use it for this and maybe the send the ETag header for the actual resource too. At least it works this way for this MS WebAPI, so if this is a different product, then still I think they use the same solution for the Graph API too. https://learn.microsoft.com/en-us/power-apps/developer/data-platform/webapi/perform-conditional-operations-using-web-api#bkmk_DetectIfChanged They might send the ETag header for the actual resource too.

Use Grace Mode for banned objects

We are trying to improve our varnish caching setup. Our backend application is fairly slow so we want to maximize the hit rate for visitors. It is not generally an issue if cached content is outdated for a little while, so response performance has priority over currentness here.
The basics are these, and they are easy to implement with the usual VCL setups:
Content not present in the cache will be retrieved as usual from the backend.
Content present in the cache within its TTL will be delivered from the cache.
Content present in the cache but older than TTL should be delivered in Grace Mode, i.e. the cache will be updated in the background while the stale content is delivered to the client. (For our scenario the grace period would be fairly long so the visitor is ensured to get a cached result. We'll employ some form of cache warming to cache fresh content when needed.)
To make backend updates visible we use fairly usual bans like these: ban("req.http.host ~ (?i)[www\.example\.com|www\.example\.net] && req.url ~ ^/products/?$");. Our project has many domains and URLs so this affords us a reasonable amount of specificity so we don't have to invalidate the entire cache all the time.
Now comes the bit we are struggling with. When a ban() is issued it will fully invalidate the cached objects. The next request will be passed through to the backend. We would like to prevent that.
What we would like is a Grace Mode-like handling in this case. When we tell Varnish "forget all URLs beginning with /products" it should use the existing cached objects, but treat them as if the TTL had expired. So the first visitor to an affected URL will get the stale cached result (immediately, while Varnish retrieves a new result), but the second visitor will get a fresh result.
I understand that we could do something like this with req.hash_always_miss if we are working on a single object, but how can we do this with a large number of objects/URLs? Due to the structure of the project we do not have an exhaustive list of all URLs. And it seems pretty prohibitive to issue quite possibly thousands of requests to Varnish when we need to update the cache.
In short: Is there a way to "ban" objects (based on URL regexes) while employing Grace Mode for all existing objects to ensure fast response times?
Unfortunately there is no soft ban function.
The only thing I can give you is a soft purge function, that is part of vmod_purge, but it doesn't support regular expressions.
See http://varnish-cache.org/docs/6.0/reference/vmod_generated.html#func-soft for more info. Although it's not exactly what you're looking for, it's better than nothing.
Here's the VCL code:
vcl 4.1;
import purge;
sub vcl_recv {
if(req.method == "SOFTPURGE") {
return(hash);
}
}
sub vcl_hit {
if(req.method == "SOFTPURGE") {
purge.soft(0s,100s);
}
}

Does node-cache uses locks

I'm trying to understand if the node-cache package uses locks for the cache object and can't find anything.
I tried to look at the source code and it doesn't look like it, but this answer suggests otherwise with the quote:
So there is Redis and node-cache for memory locks.
This cache is used in a CRUD server and I want to make sure that GET/UPDATE requests will not create a race condition on the data.
I don't see any evidence of locking in the code.
If two requests for the same key which is not in the cache are made one after the other, then it will launch two separate fetch() operations and whichever request comes back last is the one that will remain in the cache. This is probably not normally a problem, but an improved implementation could make only one request for that same key and have the second request just wait for the first request to provide the value that was already in flight.
Since the cache itself is all in-memory, all access to the cache is synchronous and thus regulated by Javascript's single threaded nature. So, the only place concurrency issues could affect things in the cache code itself are when they launch an asynchronous fetch() operation.
There are, of course, race conditions waiting to happen in how one uses the code that accesses the data just like there are with a database interface so the calling code has to be smart about how it uses the interface to avoid creating race conditions because of how it calls things.
Unfortunately no, you can write a unit test to confirm it.
I have written a library to fix that and also added read through method to easy the code usage:
https://github.com/KhanhPham2411/node-cache-async-lock

Prevent certain optionset changes in CRM via plugin

Is it possible to have a plugin intervene when someone is editing an optionset?
I would have thought crm would prevent the removal of optionset values if there are entities that refer to them, but apparently this is not the case (there are a number of orphaned fields that refer to options that no longer exist). Is there a message/entity pair that I could use to check if there are entities using the value that is to be deleted/modified and stop it if there are?
Not sure if this is possible, but you could attempt to create a plugin on the Execute Method, and check the input parameters in the context to determine what the Request Type that is being processed is. Pretty sure you'll be wanting to look for either UpdateAttributeRequest for local OptionSets, or potentially UpdateOptionSetRequest for both. Then you could run additional logic to determine what values are changing, and ensuring the database values are correct.
The big caveat to this, is if you even have a moderate amount of data, I'm guessing you'll hit the 2 minute limit for plugin execution and it will fail.

What's the best way to keep count of the data set size information in Core Data?

Right now whenever I need to access my data set size (and it can be quite frequently), I perform a countForFetchRequest on the managedObjectContext. Is this a bad thing to do? Should I manage the count locally instead? The reason I went this route is to ensure I am getting 100% correct answer. With Core Data being accessed from more than one places (for example, through NSFetchedResultsController as well), it's hard to keep an accurate count locally.
-countForFetchRequest: is always evaluated in the persistent store. When using the Sqlite store, this will result in IO being performed.
Suggested strategy:
Cache the count returned from -countForFetchRequest:.
Observe NSManagedObjectContextObjectsDidChangeNotification for your own context.
Observe NSManagedObjectContextDidSaveNotification for related contexts.
For the simple case (no fetch predicate) you can update the count from the information contained in the notification without additional IO.
Alternately, you can invalidate your cached count and refresh via -countForFetchRequest: as necessary.

Resources