Merge lp:~jameinel/loggerhead/less_work_for_head_716217 into lp:loggerhead
Status: | Work in progress |
---|---|
Proposed branch: | lp:~jameinel/loggerhead/less_work_for_head_716217 |
Merge into: | lp:loggerhead |
Prerequisite: | lp:~jameinel/loggerhead/head_middleware |
Diff against target: |
266 lines (+129/-24) 6 files modified
NEWS (+7/-13) loggerhead/controllers/__init__.py (+39/-3) loggerhead/controllers/changelog_ui.py (+15/-0) loggerhead/tests/__init__.py (+1/-4) loggerhead/tests/test_controllers.py (+67/-0) loggerhead/tests/test_simple.py (+0/-4) |
To merge this branch: | bzr merge lp:~jameinel/loggerhead/less_work_for_head_716217 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Loggerhead Team | Pending | ||
Review via email: mp+49182@code.launchpad.net |
Commit message
Do less work on HEAD requests for 'changes' urls, (bug #716217)
Description of the change
This is a bit of exploration in what it would take to shortcut the HEAD request.
It adds an api "validate_call()" which can do one of:
1) Return True, and set Headers to be exactly what they would be for a normal request.
2) Raise an error exception, though this should also match a normal request. This is how the
stack currently handles stuff like 404.
3) Return False, indicating "I don't know without further processing".
If (3) is triggered, then we do the request normally.
This is built on my http_head branch. It doesn't have to be, but it did find some bugs in the code.
What it *really* pointed out to me, is how hard it is to test loggerhead code, how many edge cases raise random errors rather than clean http error codes, and how much argument handling is handled very late in the game.
Specifically for '/changes', you can have arguments of the form:
/changes/
revid could be a revno, which gets validated fairly early. However, if it is a revid that isn't in the ancestry of the branch, it fails rather late (after we've started trying to find the history, and we've already loaded the branch cache, etc.)
If a file path is passed, then we map it to a file id. So we'd have to test the inventory at a given revision, etc.
So while I can certainly make it quick to answer the HEAD request that we have haproxy requesting, it is *very hard* to do it generically.
the only bit that we could do more easily is to *not* expand the template if we're answering a HEAD request.
Unmerged revisions
- 429. By John A Meinel
-
Merge trunk in, resolving merge conflicts.
- 428. By John A Meinel
-
Cleanups from Martin's review.
- 427. By John A Meinel
-
Find a case that isn't handled easily, punt.
Note that the tests assert what error is raised, but we really want a better one.
Not worth fixing until we get more of old trunk/experimental merged. - 426. By John A Meinel
-
Add some comments, realize that we probably still give the wrong value for a HEAD
if a revid is requested that isn't in the path. - 425. By John A Meinel
-
Add some tests for the ChangeLogUI, and implement a method for cheesing HEAD requests.
Basically, if we can answer quickly that HEAD is ok, do so, but allow fallbacks
that do it the way we used to, rather than requiring we handle all processing
immediately.
Thanks for having a go at that. I see your point about it being hard
to be sure it will work and this approach sounds good. It gives us a
way to make particular things faster if we care.
+ # Since HEAD is supposed to match GET, shouldn't we be doing something
+ # like sorting the headers?
I don't think the headers are considered to be ordered, or that anyone
would complain they were in a different order.
On a brief read through it looks good
> === modified file 'loggerhead/ controllers/ __init_ _.py' controllers/ __init_ _.py 2009-10-17 08:59:33 +0000 controllers/ __init_ _.py 2011-02-10 05:28:12 +0000 View(object) :
> --- loggerhead/
> +++ loggerhead/
> @@ -49,8 +49,18 @@
>
>
> class TemplatedBranch
> + """Base class for most views.
> +
> + This is based on the idea that .get_values() will populate a dict with
> + values for a template, which will then be expanded and returned for a given
> + request.
> +
> + def validate_call(self, path, kwargs, headers):
> + if path is not None or kwargs or self.args:
> + # This includes a file-id, abort for now
> + return False
> + # Make sure we have a valid revid
> + # XXX: If revid is a string and not in the history of the branch, we
> + # won't detect that here. That is done as part of get_view. For
> + # now, if self.args is not empty, we just abort above.
> + self.get_revid()
> + # Note: We know it is safe to return True, because we don't set any
> + # actual headers. As long as path is None and there aren't
> + # kwargs, then the only remaining bit is if revid is not actually
> + # part of the branch, we can fail early.
> + return True
> +
I wouldn't say 'abort' which sounds like failing the request; rather
'have to actually render it' or something.