Right now we go directly from vcl_hash{} to either vcl_hit{}, vcl_miss{}
or vcl_pass{} depending on the outcome, and that means, amongst other
things, that a VCL implementation of "PURGE" as to add code to all those.

Furthermore we have some semi-magic things going on behind the scenes,
such as grace and saint modes.

Assume:

* Backend fetches will be done by a different thread than the one
  processing the clients request.

* vcl_hash{} always is followed by vcl_lookup{} and that the above mentioned
  logic gets moved to VCL, rather than C code.

* vcl_hit{} goes away.

Then a plausible default vcl_lookup{} could then look like:

        sub vcl_lookup {

                if (!obj) {
                        // Miss:  Start a background fetch in another thread
                        // We come back here, when the status of that fetch
                        // is available. (ie: we go on the waiting list)
                        return (miss);
                }

                if (obj.ttl <= 0s &&
                    obj.ttl > -req.grace && obj.ttl > -obj.grace) {
                        // We have a grace situation
                        if (!obj.busy) {
                                // Nobody is fetching yet, so start a
                                // background fetch
                                background_fetch();
                        }
                        // NB: First client does not hang on the fetch
                        return (deliver);
                }

                if (obj.ttl <= 0s) {
                        // object is too old, fetch new one (see miss)
                        return (miss);
                }

                return (deliver);
        }

Possible customizations:

Purging:

        if (req.request == "PURGE") {
                // We pressume access control was in vcl_recv{}
                return (purge);
                return (purge_all);
        }

Prefetching:

        if (obj.ttl < 2s && !obj.busy) {
                // Close to deadline, pre-fetch
                background_fetch();
        }

Don't stream, only deliver complete objects:

        if (!obj.complete) {
                wait_complete(obj);
        }

I'm seriously pondering if saintmode should become a vmod at the same
time, in which case it would probably look something like:

        sub vcl_lookup {
                if (obj.ttl <= 0s && !saint.ok(req.backend, req.url)) {
                        return (deliviver)
                }
        }

        sub vcl_fetch {
                if (beresp.status >= 400) {
                        saint.bad(bereq.backend, bereq.url);
                }
        }

-- 
Poul-Henning Kamp       | UNIX since Zilog Zeus 3.20
[email protected]         | TCP/IP since RFC 956
FreeBSD committer       | BSD since 4.3-tahoe
Never attribute to malice what can adequately be explained by incompetence.

_______________________________________________
varnish-dev mailing list
[email protected]
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev

Reply via email to