Skip to content

Commit 7a5b152

Browse files
feat: async refresh of agenda data (ietf-tools#8146)
1 parent 19d80ff commit 7a5b152

3 files changed

Lines changed: 54 additions & 18 deletions

File tree

ietf/meeting/tasks.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Copyright The IETF Trust 2024, All Rights Reserved
2+
#
3+
# Celery task definitions
4+
#
5+
from celery import shared_task
6+
7+
from .views import generate_agenda_data
8+
9+
10+
@shared_task
11+
def agenda_data_refresh():
12+
generate_agenda_data(force_refresh=True)

ietf/meeting/tests_views.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from django.urls import reverse as urlreverse
2727
from django.conf import settings
2828
from django.contrib.auth.models import User
29+
from django.core.serializers.json import DjangoJSONEncoder
2930
from django.test import Client, override_settings
3031
from django.db.models import F, Max
3132
from django.http import QueryDict, FileResponse
@@ -49,7 +50,7 @@
4950
from ietf.meeting.utils import add_event_info_to_session_qs, participants_for_meeting
5051
from ietf.meeting.utils import create_recording, get_next_sequence, bluesheet_data
5152
from ietf.meeting.views import session_draft_list, parse_agenda_filter_params, sessions_post_save, agenda_extract_schedule
52-
from ietf.meeting.views import get_summary_by_area, get_summary_by_type, get_summary_by_purpose
53+
from ietf.meeting.views import get_summary_by_area, get_summary_by_type, get_summary_by_purpose, generate_agenda_data
5354
from ietf.name.models import SessionStatusName, ImportantDateName, RoleName, ProceedingsMaterialTypeName
5455
from ietf.utils.decorators import skip_coverage
5556
from ietf.utils.mail import outbox, empty_outbox, get_payload_text
@@ -245,30 +246,34 @@ def test_meeting_agenda(self):
245246

246247
# Agenda API tests
247248
# -> Meeting data
248-
r = self.client.get(urlreverse("ietf.meeting.views.api_get_agenda_data", kwargs=dict(num=meeting.number)))
249-
self.assertEqual(r.status_code, 200)
250-
rjson = json.loads(r.content.decode("utf8"))
251-
self.assertJSONEqual(
252-
r.content.decode("utf8"),
249+
# First, check that the generation function does the right thing
250+
generated_data = generate_agenda_data(meeting.number)
251+
self.assertEqual(
252+
generated_data,
253253
{
254254
"meeting": {
255255
"number": meeting.number,
256256
"city": meeting.city,
257257
"startDate": meeting.date.isoformat(),
258258
"endDate": meeting.end_date().isoformat(),
259-
"updated": rjson.get("meeting").get("updated"), # Just expect the value to exist
259+
"updated": generated_data.get("meeting").get("updated"), # Just expect the value to exist
260260
"timezone": meeting.time_zone,
261261
"infoNote": meeting.agenda_info_note,
262262
"warningNote": meeting.agenda_warning_note
263263
},
264-
"categories": rjson.get("categories"), # Just expect the value to exist
264+
"categories": generated_data.get("categories"), # Just expect the value to exist
265265
"isCurrentMeeting": True,
266-
"usesNotes": False, # make_meeting_test_data sets number=72
267-
"schedule": rjson.get("schedule"), # Just expect the value to exist
266+
"usesNotes": False, # make_meeting_test_data sets number=72
267+
"schedule": generated_data.get("schedule"), # Just expect the value to exist
268268
"floors": []
269269
}
270270
)
271-
# -> Session Materials
271+
with patch("ietf.meeting.views.generate_agenda_data", return_value=generated_data):
272+
r = self.client.get(urlreverse("ietf.meeting.views.api_get_agenda_data", kwargs=dict(num=meeting.number)))
273+
self.assertEqual(r.status_code, 200)
274+
# json.dumps using the DjangoJSONEncoder to handle timestamps consistently
275+
self.assertJSONEqual(r.content.decode("utf8"), json.dumps(generated_data, cls=DjangoJSONEncoder))
276+
# -> Session MaterialM
272277
r = self.client.get(urlreverse("ietf.meeting.views.api_get_session_materials", kwargs=dict(session_id=session.id)))
273278
self.assertEqual(r.status_code, 200)
274279
rjson = json.loads(r.content.decode("utf8"))

ietf/meeting/views.py

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from wsgiref.handlers import format_date_time
2626

2727
from django import forms
28+
from django.core.cache import caches
2829
from django.shortcuts import render, redirect, get_object_or_404
2930
from django.http import (HttpResponse, HttpResponseRedirect, HttpResponseForbidden,
3031
HttpResponseNotFound, Http404, HttpResponseBadRequest,
@@ -1657,8 +1658,16 @@ def agenda(request, num=None, name=None, base=None, ext=None, owner=None, utc=""
16571658
}
16581659
})
16591660

1660-
@cache_page(5 * 60)
1661-
def api_get_agenda_data (request, num=None):
1661+
1662+
def generate_agenda_data(num=None, force_refresh=False):
1663+
"""Generate data for the api_get_agenda_data endpoint
1664+
1665+
:num: meeting number
1666+
:force_refresh: True to force a refresh of the cache
1667+
"""
1668+
cache = caches["default"]
1669+
cache_timeout = 6 * 60
1670+
16621671
meeting = get_ietf_meeting(num)
16631672
if meeting is None:
16641673
raise Http404("No such full IETF meeting")
@@ -1667,6 +1676,12 @@ def api_get_agenda_data (request, num=None):
16671676
else:
16681677
pass
16691678

1679+
cache_key = f"generate_agenda_data_{meeting.number}"
1680+
if not force_refresh:
1681+
cached_value = cache.get(cache_key)
1682+
if cached_value is not None:
1683+
return cached_value
1684+
16701685
# Select the schedule to show
16711686
schedule = get_schedule(meeting, None)
16721687

@@ -1685,10 +1700,8 @@ def api_get_agenda_data (request, num=None):
16851700

16861701
# Get Floor Plans
16871702
floors = FloorPlan.objects.filter(meeting=meeting).order_by('order')
1688-
1689-
#debug.show('all([(item.acronym,item.session.order_number,item.session.order_in_meeting()) for item in filtered_assignments])')
1690-
1691-
return JsonResponse({
1703+
1704+
result = {
16921705
"meeting": {
16931706
"number": schedule.meeting.number,
16941707
"city": schedule.meeting.city,
@@ -1704,7 +1717,13 @@ def api_get_agenda_data (request, num=None):
17041717
"usesNotes": meeting.uses_notes(),
17051718
"schedule": list(map(agenda_extract_schedule, filtered_assignments)),
17061719
"floors": list(map(agenda_extract_floorplan, floors))
1707-
})
1720+
}
1721+
cache.set(cache_key, result, timeout=cache_timeout)
1722+
return result
1723+
1724+
1725+
def api_get_agenda_data(request, num=None):
1726+
return JsonResponse(generate_agenda_data(num, force_refresh=False))
17081727

17091728

17101729
def api_get_session_materials(request, session_id=None):

0 commit comments

Comments
 (0)