Skip to content

Commit 2005bde

Browse files
committed
Fix and test report generation locking for results views, fixes #1749
1 parent b3e813a commit 2005bde

File tree

4 files changed

+39
-6
lines changed

4 files changed

+39
-6
lines changed

integration_tests/batch/test_batch.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def test_batch_openapi(page):
6464
expect(response).to_be_ok()
6565

6666

67-
def test_batch_request(unique_id, register_test_user, test_domain):
67+
def test_batch_request(unique_id, register_test_user, test_domain, docker_compose_exec):
6868
"""A test via the Batch API should succeed."""
6969
request_data = {"type": "web", "domains": [test_domain], "name": unique_id}
7070

@@ -129,6 +129,21 @@ def test_batch_request(unique_id, register_test_user, test_domain):
129129
response = requests.get(report_url, verify=False)
130130
assert response.status_code == 200, "test results should be publicly accessible without authentication"
131131

132+
# delete result files (this can happen in production when cleanup is done by a cron job)
133+
docker_compose_exec("app", "sh -c 'rm -v /app/batch_results/*'")
134+
135+
# try to get batch results again after files have been deleted (this should trigger a new generation task)
136+
results_response = requests.get(INTERNETNL_API + "requests/" + test_id + "/results", auth=auth, verify=False)
137+
# expect error because result need to be generated again
138+
assert results_response.status_code == 400
139+
assert "Report is being generated." in results_response.text
140+
141+
# get batch results again after starting generation
142+
results_response = requests.get(INTERNETNL_API + "requests/" + test_id + "/results", auth=auth, verify=False)
143+
print(f"{results_response.text=}")
144+
results_response.raise_for_status()
145+
print("api results JSON:", results_response.text)
146+
132147

133148
def test_batch_static_requires_no_auth():
134149
"""Static files should be available without authentication for viewing batch results."""

interface/batch/util.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,9 @@ def on_failure(exc, task_id, args, kwargs, einfo):
273273
results = gather_batch_results_technical(user, batch_request, site_url)
274274
save_batch_results_to_file(user, batch_request, results, technical=True)
275275

276+
request_lock_id = redis_id.batch_results_request_lock.id.format(batch_request.request_id)
277+
cache.delete(request_lock_id)
278+
276279

277280
def gather_batch_results(user, batch_request, site_url):
278281
"""

interface/batch/views.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
register_request,
2727
)
2828
from internetnl import log
29+
from .util import request_already_generating
2930

3031

3132
@require_http_methods(["GET", "POST"])
@@ -70,9 +71,10 @@ def results(request, request_id, *args, technical=False, **kwargs):
7071
return bad_client_request_response("The request is not yet `done`.")
7172
else:
7273
if not batch_request.has_report_file():
74+
if request_already_generating(batch_request.request_id):
75+
return bad_client_request_response("Report is already being generated.")
7376
batch_async_generate_results.delay(user=user, batch_request=batch_request, site_url=get_site_url(request))
74-
return bad_client_request_response("The request is not yet `done`.")
75-
77+
return bad_client_request_response("Report is being generated.")
7678
else:
7779
report_file = batch_request.get_report_file(technical)
7880
try:

interface/test/batch/test_batch.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from django.core.cache import cache
44
from checks.models import BatchRequest, BatchRequestType, BatchUser, BatchRequestStatus
55
from interface.batch.util import get_request, register_request
6+
from interface.batch.views import results
67
from django.test.client import RequestFactory
78
import pytest
89
from interface.batch.util import batch_async_generate_results
@@ -68,15 +69,27 @@ def test_batch_request_result_generation(db, client, mocker):
6869
batch_request.save()
6970

7071
# if batch request is done, a batch_async_generate_results task should be put on the queue to generate the results
71-
get_request(request, batch_request, test_user)
72+
response = get_request(request, batch_request, test_user)
73+
assert response.status_code == 200
74+
assert json.loads(response.content)["request"]["status"] == "generating"
7275
assert batch_async_generate_results.delay.call_count == 1
7376

7477
# there should not be an additional task put on the queue when one is already present
75-
get_request(request, batch_request, test_user)
78+
response = get_request(request, batch_request, test_user)
79+
assert response.status_code == 200
80+
assert json.loads(response.content)["request"]["status"] == "generating"
81+
assert batch_async_generate_results.delay.call_count == 1
82+
83+
# when directly accessing results there should also not be a extra task added to the queue
84+
assert (
85+
results(request, batch_request.request_id, batch_user=test_user).status_code == 400
86+
), "should return `bad_client_request_response`"
7687
assert batch_async_generate_results.delay.call_count == 1
7788

7889
# if the cache expires a new batch_async_generate_results task can be added
7990
lock_id = redis_id.batch_results_request_lock.id.format(batch_request.request_id)
8091
cache.delete(lock_id)
81-
get_request(request, batch_request, test_user)
92+
response = get_request(request, batch_request, test_user)
93+
assert response.status_code == 200
94+
assert json.loads(response.content)["request"]["status"] == "generating"
8295
assert batch_async_generate_results.delay.call_count == 2

0 commit comments

Comments
 (0)