Merge lp:~leonardr/lazr.restful/disable-cache into lp:lazr.restful

Proposed by Leonard Richardson
Status: Merged
Merged at revision: 133
Proposed branch: lp:~leonardr/lazr.restful/disable-cache
Merge into: lp:lazr.restful
Diff against target: 163 lines (+94/-12)
4 files modified
src/lazr/restful/NEWS.txt (+7/-2)
src/lazr/restful/_resource.py (+21/-9)
src/lazr/restful/example/base/tests/representation-cache.txt (+59/-1)
src/lazr/restful/interfaces/_rest.py (+7/-0)
To merge this branch: bzr merge lp:~leonardr/lazr.restful/disable-cache
Reviewer Review Type Date Requested Status
LAZR Developers Pending
Review via email: mp+26713@code.launchpad.net

Description of the change

This branch adds a configuration option enable_server_side_representation_cache, which lets you disable the representation cache without un-registering it. I'll be using this to control the memcached representation cache in Launchpad with a Launchpad configuration setting. I have two goals.

1) Make it possible to test the cache in staging without having to deploy different code to staging and production.
2) Make it easy for the LOSAs to disable the cache if something goes wrong in production.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/lazr/restful/NEWS.txt'
2--- src/lazr/restful/NEWS.txt 2010-06-02 17:04:40 +0000
3+++ src/lazr/restful/NEWS.txt 2010-06-03 14:51:24 +0000
4@@ -2,8 +2,13 @@
5 NEWS for lazr.restful
6 =====================
7
8-0.9.28 (Development)
9-====================
10+0.9.28 (2010-06-03)
11+===================
12+
13+Special note: This version adds a new configuration element,
14+'enable_server_side_representation_cache'. This lets you turn the
15+representation cache on and off at runtime without unregistering the
16+cache utility.
17
18 Fixed some test failures.
19
20
21=== modified file 'src/lazr/restful/_resource.py'
22--- src/lazr/restful/_resource.py 2010-06-03 14:26:13 +0000
23+++ src/lazr/restful/_resource.py 2010-06-03 14:51:24 +0000
24@@ -1527,22 +1527,21 @@
25 if media_type in [self.WADL_TYPE, self.DEPRECATED_WADL_TYPE]:
26 return self.toWADL().encode("utf-8")
27 elif media_type == self.JSON_TYPE:
28- cache = None
29- try:
30- cache = getUtility(IRepresentationCache)
31+ cache = self._representation_cache
32+ if cache is None:
33+ representation = None
34+ else:
35 representation = cache.get(
36 self.context, self.JSON_TYPE, self.request.version)
37- except ComponentLookupError:
38- # There's no representation cache.
39- representation = None
40
41 redacted_fields = self.redacted_fields
42 if representation is None:
43- # Either there is no cache, or the representation
44+ # Either there is no active cache, or the representation
45 # wasn't in the cache.
46 representation = simplejson.dumps(self, cls=ResourceJSONEncoder)
47- # If there's a cache, and this representation doesn't
48- # contain any redactions, store it in the cache.
49+ # If there's an active cache, and this representation
50+ # doesn't contain any redactions, store it in the
51+ # cache.
52 if cache is not None and len(redacted_fields) == 0:
53 cache.set(self.context, self.JSON_TYPE,
54 self.request.version, representation)
55@@ -1569,6 +1568,19 @@
56 "No representation implementation for media type %s"
57 % media_type)
58
59+ @property
60+ def _representation_cache(self):
61+ """Return the representation cache, or None if missing/disabled."""
62+ try:
63+ cache = getUtility(IRepresentationCache)
64+ except ComponentLookupError:
65+ # There's no representation cache.
66+ return None
67+ config = getUtility(IWebServiceConfiguration)
68+ if config.enable_server_side_representation_cache:
69+ return cache
70+ return None
71+
72
73 class CollectionResource(BatchingResourceMixin,
74 CustomOperationResourceMixin,
75
76=== modified file 'src/lazr/restful/example/base/tests/representation-cache.txt'
77--- src/lazr/restful/example/base/tests/representation-cache.txt 2010-05-24 13:52:30 +0000
78+++ src/lazr/restful/example/base/tests/representation-cache.txt 2010-06-03 14:51:24 +0000
79@@ -259,7 +259,65 @@
80 This representation is from the cache.
81 This representation is from the cache.
82
83-Cleanup: de-register the cache.
84+enable_server_side_representation_cache
85+=======================================
86+
87+A configuration setting allows you to disable the cache without
88+de-registering it. This is useful when you're debugging a cache
89+implementation or a cache invalidation algorithm.
90+
91+ >>> from lazr.restful.interfaces import IWebServiceConfiguration
92+ >>> config = getUtility(IWebServiceConfiguration)
93+ >>> print config.enable_server_side_representation_cache
94+ True
95+
96+Set this configuration value to False, and representations will not be
97+served from the cache, even if present.
98+
99+ >>> config.enable_server_side_representation_cache = False
100+ >>> recipes = webservice.get("/recipes").jsonBody()['entries']
101+ >>> for instructions in (
102+ ... sorted(recipe['instructions'] for recipe in recipes)):
103+ ... print instructions
104+ A perfectly roasted chicken is...
105+ Draw, singe, stuff, and truss...
106+ Preheat oven to...
107+ You can always judge...
108+
109+New representations will not be added to the cache.
110+
111+ >>> before_keys = len(dictionary.keys())
112+ >>> dishes = webservice.get("/dishes")
113+ >>> len(dictionary.keys()) == before_keys
114+ True
115+
116+The cache is still registered as a utility.
117+
118+ >>> print getUtility(IRepresentationCache)
119+ <lazr.restful.simple.DictionaryBasedRepresentationCache object ...>
120+
121+And it's still populated, as we can see by re-enabling it.
122+
123+ >>> config.enable_server_side_representation_cache = True
124+ >>> recipes = webservice.get("/recipes").jsonBody()['entries']
125+ >>> for instructions in (
126+ ... sorted(recipe['instructions'] for recipe in recipes)):
127+ ... print instructions
128+ This representation is from the cache.
129+ This representation is from the cache.
130+ This representation is from the cache.
131+ This representation is from the cache.
132+
133+Once re-enabled, new representations are once again added to the cache.
134+
135+ >>> dishes = webservice.get("/dishes")
136+ >>> len(dictionary.keys()) > before_keys
137+ True
138+
139+Cleanup
140+=======
141+
142+De-register the cache.
143
144 >>> sm.registerUtility(None, IRepresentationCache)
145
146
147=== modified file 'src/lazr/restful/interfaces/_rest.py'
148--- src/lazr/restful/interfaces/_rest.py 2010-05-24 13:00:07 +0000
149+++ src/lazr/restful/interfaces/_rest.py 2010-06-03 14:51:24 +0000
150@@ -409,6 +409,13 @@
151 service root for the latest version (which probably changes more
152 often).""")
153
154+ enable_server_side_representation_cache = Bool(
155+ title=u"Enable the server-side representation cache.",
156+ default=True,
157+ description=u"""If this is false, the server-side representation
158+ cache will not be used, even if one is registered."""
159+ )
160+
161 service_description = TextLine(
162 title=u"Service description",
163 description=u"""A human-readable description of the web service.

Subscribers

People subscribed via source and target branches