Use Grace Mode for banned objects - varnish

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);
}
}

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.

Best way for Node.js server to return an error before process runs out of heap memory

I'm running Node.js / Express server on a container with pretty strict memory constraints.
One of the endpoints I'd like to expose is a "batch" endpoint where a client can request a list of data objects in bulk from my data store. The individual objects vary in size, so it's difficult to set a hard limit on how many objects can be requested at one time. In most cases a client could request a large amount of objects without any issues, but it certain edge cases even requests for a small amount of objects will trigger an OOM error.
I'm familiar with Node's process.memoryUsage() & process.memoryUsage.rss(), but I'm worried about the performance implications of constantly checking heap (or service) memory usage while serving an individual batch request.
In the longer term, I might consider using memory monitoring to bake in some automatic pagination for the endpoint. In the short term, however, I'd just like to be able to return an informative error to the client in the event that they are requesting too many data objects at a given time (rather than have the entire application crash with an OOM error).
Are there any more effective methods or tools I could be using to solve the problem instead?
you have couple of options.
Options 1.
what is biggest object you have in store. I would say that you allow some {max object count} on api and set container memory to biggestObject x {max allowed objects size}. You can even have some pagination concept added if required where page size = {max object count}
Option 2.
Also using process.memoryUsage() should be fine too. I don't believe it is a not a costly call unless you have read this somewhere. Before each object pull check current memory and go ahead only if safe amount of memory is available.The response in this case can contain only pulled data and lets client to pull remaining ids in next call. Implementable via some paging logic too.
options 3.
explore streams. This I will not be able to add much info for now.

Purge varnish cache based on request header values

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.

How to manage concurrency for page blobs?

I want to have multiple clients writing to the same page, and if a race condition occurs then I want all but one to fail and then retry (sort of like ETags on the entire blob).
According to this, https://learn.microsoft.com/en-us/azure/storage/storage-concurrency#managing-concurrency-in-blob-storage, Put Page returns an ETag value, but is that only for the entire page blob? I think it's not for every page right?
Also in https://learn.microsoft.com/en-us/rest/api/storageservices/fileservices/put-page there's a section "Managing Concurrency Issues", which says that ETag works well if the number of concurrent writes is relatively low - I assume this is because it indeed won't work on each page.
I am not sure which options I am left with? It seems all of the options apply to the blob as a whole. I high number of concurrent writes to the same blob, and low to moderate to the same page.

Should I cache results of functions involving mass file I/O in a node.js server app?

I'm writing my first 'serious' Node/Express application, and I'm becoming concerned about the number of O(n) and O(n^2) operations I'm performing on every request. The application is a blog engine, which indexes and serves up articles stored in markdown format in the file system. The contents of the articles folder do not change frequently, as the app is scaled for a personal blog, but I would still like to be able to add a file to that folder whenever I want, and have the app include it without further intervention.
Operations I'm concerned about
When /index is requested, my route is iterating over all files in the directory and storing them as objects
When a "tag page" is requested (/tag/foo) I'm iterating over all the articles, and then iterating over their arrays of tags to determine which articles to present in an index format
Now, I know that this is probably premature optimisation as the performance is still satisfactory over <200 files, but definitely not lightning fast. And I also know that in production, measures like this wouldn't be considered necessary/worthwhile unless backed by significant benchmarking results. But as this is purely a learning exercise/demonstration of ability, and as I'm (perhaps excessively) concerned about learning optimal habits and patterns, I worry I'm committing some kind of sin here.
Measures I have considered
I get the impression that a database might be a more typical solution, rather than filesystem I/O. But this would mean monitoring the directory for changes and processing/adding new articles to the database, a whole separate operation/functionality. If I did this, would it make sense to be watching that folder for changes even when a request isn't coming in? Or would it be better to check the freshness of the database, then retrieve results from the database? I also don't know how much this helps ultimately, as database calls are still async/slower than internal state, aren't they? Or would a database query, e.g. articles where tags contain x be O(1) rather than O(n)? If so, that would clearly be ideal.
Also, I am beginning to learn about techniques/patterns for caching results, e.g. a property on the function containing the previous result, which could be checked for and served up without performing the operation. But I'd need to check if the folder had new files added to know if it was OK to serve up the cached version, right? But more fundamentally (and this is the essential newbie query at hand) is it considered OK to do this? Everyone talks about how node apps should be stateless, and this would amount to maintaining state, right? Once again, I'm still a fairly raw beginner, and so reading the source of mature apps isn't always as enlightening to me as I wish it was.
Also have I fundamentally misunderstood how routes work in node/express? If I store a variable in index.js, are all the variables/objects created by it destroyed when the route is done and the page is served? If so I apologise profusely for my ignorance, as that would negate basically everything discussed, and make maintaining an external database (or just continuing to redo the file I/O) the only solution.
First off, the request and response objects that are part of each request last only for the duration of a given request and are not shared by other requests. They will be garbage collected as soon as they are no longer in use.
But, module-scoped variables in any of your Express modules last for the duration of the server. So, you can load some information in one request, store it in a module-level variable and that information will still be there when the next request comes along.
Since multiple requests can be "in-flight" at the same time if you are using any async operations in your request handlers, then if you are sharing/updating information between requests you have to make sure you have atomic updates so that the data is shared safely. In node.js, this is much simpler than in a multi-threaded response handler web server, but there still can be issues if you're doing part of an update to a shared object, then doing some async operation, then doing the rest of an update to a shared object. When you do an async operation, another request could run and see the shared object.
When not doing an async operation, your Javascript code is single threaded so other requests won't interleave until you go async.
It sounds like you want to cache your parsed state into a simple in-memory Javascript structure and then intelligently update this cache of information when new articles are added.
Since you already have the code to parse your set of files and tags into in-memory Javascript variables, you can just keep that code. You will want to package that into a separate function that you can call at any time and it will return a newly updated state.
Then, you want to call it when your server starts and that will establish the initial state.
All your routes can be changed to operate on the cached state and this should speed them up tremendously.
Then, all you need is a scheme to decide when to update the cached state (e.g. when something in the file system changed). There are lots of options and which to use depends a little bit on how often things will change and how often the changes need to get reflected to the outside world. Here are some options:
You could register a file system watcher for a particular directory of your file system and when it triggers, you figure out what has changed and update your cache. You can make the update function as dumb (just start over and parse everything from scratch) or as smart (figure out what one item changed and update only that part of the cache) as it is worth doing. I'd suggest you start simple and only invest more in it when you're sure that effort is needed.
You could just manually rebuild the cache once every hour. Updates would take an average of 30 minutes to show, but this would take 10 seconds to implement.
You could create an admin function in your server to instruct the server to update its cache now. This might be combined with option 2, so that if you added new content, it would automatically show within an hour, but if you wanted it to show immediately, you could hit the admin page to tell it to update its cache.

Resources