Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Balogh <jbalogh@mozilla.com>2010-09-03 18:40:49 (GMT)
committer Jeff Balogh <jbalogh@mozilla.com>2010-09-03 18:40:49 (GMT)
commit0af82fe265fcc3adace2dca6b9f38b7fe3fba91e (patch)
treeecd7bc921c854f09ca4d2deb2ff2fbcb3fb70950
parentc3a5f6371e804b301a83814ae56a82bc49a1b90a (diff)
context managers for hitting master and turning off caching
-rw-r--r--apps/amo/decorators.py10
-rw-r--r--apps/amo/models.py35
-rw-r--r--apps/bandwagon/views.py14
3 files changed, 56 insertions, 3 deletions
diff --git a/apps/amo/decorators.py b/apps/amo/decorators.py
index 18bfc71..a1a7f6c 100644
--- a/apps/amo/decorators.py
+++ b/apps/amo/decorators.py
@@ -1,3 +1,4 @@
+import contextlib
import functools
import json
@@ -5,6 +6,7 @@ from django import http
from django.contrib.auth import decorators as auth_decorators
from django.utils.http import urlquote
+from .models import use_master, skip_cache
from .urlresolvers import reverse
@@ -58,3 +60,11 @@ def json_view(f):
json_view.error = lambda s: http.HttpResponseBadRequest(
json.dumps(s), content_type='application/json')
+
+
+def write(f):
+ @functools.wraps(f)
+ def wrapper(*args, **kw):
+ with contextlib.nested(use_master(), skip_cache()):
+ return f(*args, **kw)
+ return wrapper
diff --git a/apps/amo/models.py b/apps/amo/models.py
index b3cf400..20ea968 100644
--- a/apps/amo/models.py
+++ b/apps/amo/models.py
@@ -1,14 +1,42 @@
+import contextlib
+import threading
+
from django.db import models
from django.utils import translation
-import queryset_transform
import caching.base
+import multidb.pinning
+import queryset_transform
from translations import transformer
from . import signals
+_locals = threading.local()
+_locals.skip_cache = False
+
+
+@contextlib.contextmanager
+def use_master():
+ """Within this context, all queries go to the master."""
+ multidb.pinning.pin_this_thread()
+ try:
+ yield
+ finally:
+ multidb.pinning.unpin_this_thread()
+
+
+@contextlib.contextmanager
+def skip_cache():
+ """Within this context, no queries come from cache."""
+ _locals.skip_cache = True
+ try:
+ yield
+ finally:
+ _locals.skip_cache = False
+
+
class TransformQuerySet(queryset_transform.TransformQuerySet):
def pop_transforms(self):
@@ -57,7 +85,8 @@ CachingQuerySet.__bases__ = (TransformQuerySet,) + CachingQuerySet.__bases__
class UncachedManagerBase(models.Manager):
def get_query_set(self):
- return self._with_translations(TransformQuerySet(self.model))
+ qs = self._with_translations(TransformQuerySet(self.model))
+ return qs
def _with_translations(self, qs):
# Since we're attaching translations to the object, we need to stick
@@ -88,6 +117,8 @@ class ManagerBase(caching.base.CachingManager, UncachedManagerBase):
def get_query_set(self):
qs = super(ManagerBase, self).get_query_set()
+ if getattr(_locals, 'skip_cache', False):
+ qs = qs.no_cache()
return self._with_translations(qs)
def raw(self, raw_query, params=None, *args, **kwargs):
diff --git a/apps/bandwagon/views.py b/apps/bandwagon/views.py
index 9ee0402..88eb744 100644
--- a/apps/bandwagon/views.py
+++ b/apps/bandwagon/views.py
@@ -12,7 +12,7 @@ from tower import ugettext_lazy as _lazy, ugettext as _
from amo import messages
import amo.utils
import sharing.views
-from amo.decorators import login_required, post_required, json_view
+from amo.decorators import login_required, post_required, json_view, write
from amo.urlresolvers import reverse
from access import acl
from addons.models import Addon
@@ -203,6 +203,7 @@ def get_notes(collection, raw=False):
yield rv
+@write
@login_required
def collection_vote(request, username, slug, direction):
c = get_collection(request, username, slug)
@@ -234,6 +235,7 @@ def initial_data_from_request(request):
return dict(author=request.amo_user, application_id=request.APP.id)
+@write
@login_required
def add(request):
"Displays/processes a form to create a collection."
@@ -266,6 +268,8 @@ def add(request):
return render(request, 'bandwagon/add.html', data)
+@write
+@login_required
def ajax_new(request):
form = forms.CollectionForm(request.POST or None,
initial={'author': request.amo_user,
@@ -305,6 +309,7 @@ def ajax_list(request):
{'collections': collections})
+@write
@login_required
@post_required
def collection_alter(request, username, slug, action):
@@ -332,6 +337,7 @@ def change_addon(request, collection, action):
return redirect(url)
+@write
@login_required
@post_required
def ajax_collection_alter(request, action):
@@ -342,6 +348,7 @@ def ajax_collection_alter(request, action):
return change_addon(request, c, action)
+@write
@login_required
@owner_required(require_owner=False)
def edit(request, collection, username, slug):
@@ -393,6 +400,7 @@ def edit(request, collection, username, slug):
return render(request, 'bandwagon/edit.html', data)
+@write
@login_required
@owner_required(require_owner=False)
@post_required
@@ -407,6 +415,7 @@ def edit_addons(request, collection, username, slug):
return http.HttpResponseRedirect(collection.edit_url() + '#addons-edit')
+@write
@login_required
@owner_required
@post_required
@@ -429,6 +438,7 @@ def edit_contributors(request, collection, username, slug):
return http.HttpResponseRedirect(collection.edit_url() + '#users-edit')
+@write
@login_required
@owner_required
@post_required
@@ -440,6 +450,7 @@ def edit_privacy(request, collection, username, slug):
return redirect(collection.get_url_path())
+@write
@login_required
def delete(request, username, slug):
collection = get_object_or_404(Collection, author__username=username,
@@ -465,6 +476,7 @@ def delete(request, username, slug):
return render(request, 'bandwagon/delete.html', data)
+@write
@login_required
@post_required
@json_view