"""Middleware to defer slow denormalization at the end of a request.""" from django.core.cache import cache from mahjong_ranking import models from . import LOGGER, MIN_HANCHANS_FOR_LADDER class DenormalizationUpdateMiddleware(object): # Ignore PyLintBear (R0903) """To recalculate everything in the queues at the end of a POST request.""" def process_response(self, request, response): # Ignore PyLintBear (R0201) """Check and process the recalculation queues on each POST request. :param request: the django HttpRequest object :param response: the django HttpResponse object :return: the django HttpResponse object """ event_queue = set() season_queue = set() if request.method != 'POST': return response event_ranking_queue = cache.get('event_ranking_queue', set()) while event_ranking_queue: event_id, user_id = event_ranking_queue.pop() event_ranking = models.EventRanking.objects.get_or_create( event_id=event_id, user_id=user_id)[0] event_ranking.recalculate() event_queue.add(event_id) cache.set('event_ranking_queue', set(), 360) kyu_dan_ranking_queue = cache.get('kyu_dan_ranking_queue', set()) while kyu_dan_ranking_queue: user_id, hanchan_start = kyu_dan_ranking_queue.pop() kyu_dan_ranking = models.KyuDanRanking.objects.get_or_create( user_id=user_id)[0] kyu_dan_ranking.recalculate(hanchan_start) cache.set('kyu_dan_ranking_queue', set(), 360) ladder_ranking_queue = cache.get('ladder_ranking_queue', set()) while ladder_ranking_queue: season, user_id = ladder_ranking_queue.pop() ladder_ranking = models.SeasonRanking.objects.get_or_create( user_id=user_id, season=season)[0] ladder_ranking.recalculate() season_queue.add(season) cache.set('ladder_ranking_queue', ladder_ranking_queue, 360) for event_id in event_queue: eventranking_set = models.EventRanking.objects.filter( event_id=event_id).order_by('avg_placement', '-avg_score') placement = 1 for ranking in eventranking_set: ranking.placement = placement placement += 1 ranking.save(force_update=True) for season in season_queue: LOGGER.info(u'Recalculate placements for Season %d', season) season_rankings = models.SeasonRanking.objects.filter( season=season, hanchan_count__gt=MIN_HANCHANS_FOR_LADDER ).order_by('avg_placement', '-avg_score') placement = 1 for ranking in season_rankings: ranking.placement = placement ranking.save(force_update=True) placement += 1 return response