def test_addon_index(self): c = Collection.objects.get(pk=512) c.author = self.user eq_(c.addon_index, None) ids = c.addons.values_list('id', flat=True) c.save() eq_(c.addon_index, Collection.make_index(ids))
def test_addon_index(self): c = Collection.objects.get(pk=512) c.author = self.user eq_(c.addon_index, None) ids = c.addons.values_list("id", flat=True) c.save() eq_(c.addon_index, Collection.make_index(ids))
def recommendations(request, version, platform, limit=9): """ Figure out recommended add-ons for an anonymous user based on POSTed guids. POST body looks like {"guids": [...]} with an optional "token" key if they've been here before. """ try: POST = json.loads(request.raw_post_data) guids = POST['guids'] except (ValueError, TypeError, KeyError): # Errors: invalid json, didn't get a dict, didn't find "guids". return http.HttpResponseBadRequest() addon_ids = get_addon_ids(guids) index = Collection.make_index(addon_ids) ids, recs = Collection.get_recs_from_ids(addon_ids, request.APP, version) recs = _recommendations(request, version, platform, limit, index, ids, recs) # We're only storing a percentage of the collections we see because the db # can't keep up with 100%. if not waffle.sample_is_active('disco-pane-store-collections'): return recs # Users have a token2 if they've been here before. The token matches # addon_index in their SyncedCollection. if 'token2' in POST: token = POST['token2'] if token == index: # We've seen them before and their add-ons have not changed. return recs elif token != index: # We've seen them before and their add-ons changed. Remove the # reference to their old synced collection. (SyncedCollection.objects.filter(addon_index=index) .update(count=F('count') - 1)) # Try to create the SyncedCollection. There's a unique constraint on # addon_index so it will fail if this addon_index already exists. If we # checked for existence first and then created a collection there would # be a race condition between multiple users with the same addon_index. try: c = SyncedCollection.objects.create(addon_index=index, count=1) c.set_addons(addon_ids) except IntegrityError: try: (SyncedCollection.objects.filter(addon_index=index) .update(count=F('count') + 1)) except Exception, e: log.error(u'Could not count++ "%s" (%s).' % (index, e))
def recommendations(request, version, platform, limit=9): """ Figure out recommended add-ons for an anonymous user based on POSTed guids. POST body looks like {"guids": [...]} with an optional "token" key if they've been here before. """ try: POST = json.loads(request.raw_post_data) guids = POST['guids'] except (ValueError, TypeError, KeyError): # Errors: invalid json, didn't get a dict, didn't find "guids". return http.HttpResponseBadRequest() addon_ids = get_addon_ids(guids) index = Collection.make_index(addon_ids) ids, recs = Collection.get_recs_from_ids(addon_ids, request.APP, version) recs = _recommendations(request, version, platform, limit, index, ids, recs) # We're only storing a percentage of the collections we see because the db # can't keep up with 100%. if not waffle.sample_is_active('disco-pane-store-collections'): return recs # Users have a token2 if they've been here before. The token matches # addon_index in their SyncedCollection. if 'token2' in POST: token = POST['token2'] if token == index: # We've seen them before and their add-ons have not changed. return recs elif token != index: # We've seen them before and their add-ons changed. Remove the # reference to their old synced collection. (SyncedCollection.objects.filter(addon_index=index) .update(count=F('count') - 1)) # Try to create the SyncedCollection. There's a unique constraint on # addon_index so it will fail if this addon_index already exists. If we # checked for existence first and then created a collection there would # be a race condition between multiple users with the same addon_index. try: c = SyncedCollection.objects.create(addon_index=index, count=1) c.set_addons(addon_ids) except IntegrityError: try: (SyncedCollection.objects.filter(addon_index=index) .update(count=F('count') + 1)) except Exception, e: log.error(u'Could not count++ "%s" (%s).' % (index, e))
def get_synced_collection(addon_ids, token): """ Get a synced collection for these addons. May reuse an existing collection. The token is associated with the collection. """ index = Collection.make_index(addon_ids) try: c = (SyncedCollection.objects.no_cache().filter(addon_index=index))[0] except IndexError: c = SyncedCollection.objects.create(listed=False) c.set_addons(addon_ids) c.token_set.create(token=token) return c
def recommendations(request, limit=5): """ Figure out recommended add-ons for an anonymous user based on POSTed guids. POST body looks like {"guids": [...]} with an optional "token" key if they've been here before. """ if request.method != 'POST': return http.HttpResponseNotAllowed(['POST']) try: POST = json.loads(request.raw_post_data) guids = POST['guids'] except (ValueError, TypeError, KeyError): # Errors: invalid json, didn't get a dict, didn't find "guids". return http.HttpResponseBadRequest() addon_ids = get_addon_ids(guids) token = POST['token'] if 'token' in POST else get_random_token() if 'token' in POST: q = SyncedCollection.objects.filter(token_set__token=token) if q: # We've seen this user before. synced = q[0] if synced.addon_index == Collection.make_index(addon_ids): # Their add-ons didn't change, get out quick. recs = synced.get_recommendations() return _recommendations(request, limit, token, recs) else: # Remove the link to the current sync, make a new one below. synced.token_set.get(token=token).delete() synced = get_synced_collection(addon_ids, token) recs = synced.get_recommendations() return _recommendations(request, limit, token, recs)
POST body looks like {"guids": [...]} with an optional "token" key if they've been here before. """ if not compat_mode: compat_mode = get_compat_mode(version) try: POST = json.loads(request.raw_post_data) guids = POST['guids'] except (ValueError, TypeError, KeyError), e: # Errors: invalid json, didn't get a dict, didn't find "guids". log.debug('Recommendations return 405 because: %s' % e) return http.HttpResponseBadRequest() addon_ids = get_addon_ids(guids) index = Collection.make_index(addon_ids) ids, recs = Collection.get_recs_from_ids(addon_ids, request.APP, version, compat_mode) recs = _recommendations(request, version, platform, limit, index, ids, recs, compat_mode) # We're only storing a percentage of the collections we see because the db # can't keep up with 100%. if not waffle.sample_is_active('disco-pane-store-collections'): return recs # Users have a token2 if they've been here before. The token matches # addon_index in their SyncedCollection. if 'token2' in POST: token = POST['token2']
POST body looks like {"guids": [...]} with an optional "token" key if they've been here before. """ if not compat_mode: compat_mode = get_compat_mode(version) try: POST = json.loads(request.raw_post_data) guids = POST['guids'] except (ValueError, TypeError, KeyError), e: # Errors: invalid json, didn't get a dict, didn't find "guids". log.debug('Recommendations return 405 because: %s' % e) return http.HttpResponseBadRequest() addon_ids = get_addon_ids(guids) index = Collection.make_index(addon_ids) ids, recs = Collection.get_recs_from_ids(addon_ids, request.APP, version, compat_mode) recs = _recommendations(request, version, platform, limit, index, ids, recs, compat_mode) # We're only storing a percentage of the collections we see because the db # can't keep up with 100%. if not waffle.sample_is_active('disco-pane-store-collections'): return recs # Users have a token2 if they've been here before. The token matches # addon_index in their SyncedCollection. if 'token2' in POST: token = POST['token2']
def test_addon_index(self): c = Collection.objects.get(pk=5) eq_(c.addon_index, None) ids = c.addons.values_list('id', flat=True) c.save() eq_(c.addon_index, Collection.make_index(ids))