[PATCH] hgweb: support disabling page cache

Martin Geisler mg at lazybytes.net
Thu Apr 21 02:58:49 CDT 2011


Steven Stallion <sstallion at gmail.com> writes:

> On Wed, Apr 20, 2011 at 10:57 AM, Matt Mackall <mpm at selenic.com> wrote:
>> On Wed, 2011-04-20 at 04:02 +0000, Steven Stallion wrote:
>>> # HG changeset patch
>>> # User Steven Stallion <sstallion at gmail.com>
>>> # Date 1303272110 14400
>>> # Node ID 09c1266b7d19ac58bdef198965d44677c4021fa3
>>> # Parent  94dbe11c15c38cdf7427079035cd83417636f3db
>>> hgweb: support disabling page cache
>>>
>>> By default, hgweb_mod supports caching via the ETag header. This can
>>> cause some confusion with browsers which cache aggressively.
>>
>> "Confusion" sounds like a bug, please elaborate.
>
> Certainly.
>
> At our installation we have a class of users which tend to keep a
> browser tab open and simply refresh looking for changes to
> repositories. They expect to see the age of commits change on each
> refresh, even if there have been no changes to the actual content. I
> don't think this is a bug (at least I've seen nothing to suggest that
> so far), its just a usability tweak to keep others from derailing me
> every couple of days. I've seen something similar myself, having made
> a push the night before and refreshing a window after a day or so.

A more complete solution would be to compute when those commit ages
change. Right now we store the repository timestamp in the ETag header
which we compare with the current timestamp of the repository.

If we instead sent a Last-Modified header containing "now" to the client
on the first request, then we would get a If-Modified-Since header back
on subsequent requests. That would contain the time of the last access
by the client. The check we want to do is then

  age_now = age(repo_timestamp, now=time.time())
  age_then = age(repo_timestamp, now=modified_since)
  if repo_timestamp < modified_since and age_now == age_then:
      return HTTP_NOT_MODIFIED
  else:
      return generate_page()

The age function is similar to templatefilters.age, but takes a now
argument to determine from when the age is computed.

That way we can see if client will get a new commit age: if the last
commit was at 8:00, and the client accessed the repository at 8:15, then
at 11:00, we will compare

  age(8:00, now=11:00) == age(8:00, now=8:15)

which is

  '3 hours ago' == '15 minutes ago'

and so the client needs a new page.

This is a conservative stragety that will trigger more requests than
necessary for pages that don't contain any ages. With the ETag caching,
each commit will invalidate all pages once, with this scheme pages a
commit will invalidate pages once per second until two minutes have
passed, then once a minute until two hours have passed, then once an
hour for two days, etc.

-- 
Martin Geisler

Mercurial links: http://mercurial.ch/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: not available
URL: <http://selenic.com/pipermail/mercurial-devel/attachments/20110421/88958529/attachment.pgp>


More information about the Mercurial-devel mailing list