Skip to content
This repository was archived by the owner on May 5, 2025. It is now read-only.

Commit 4baf1ae

Browse files
authored
Bundle Analysis: dedupe caching processing (#1184)
1 parent 6f7f522 commit 4baf1ae

2 files changed

Lines changed: 168 additions & 2 deletions

File tree

tasks/bundle_analysis_processor.py

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from app import celery_app
1010
from database.enums import ReportType
11-
from database.models import Commit, Upload
11+
from database.models import Commit, CommitReport, Upload
1212
from services.bundle_analysis.report import (
1313
BundleAnalysisReportService,
1414
ProcessingResult,
@@ -114,7 +114,42 @@ def process_impl_within_lock(
114114
if upload_id is not None:
115115
upload = db_session.query(Upload).filter_by(id_=upload_id).first()
116116
else:
117-
commit_report = report_service.initialize_and_save_report(commit)
117+
# This processor task handles caching for reports. When the 'upload' parameter is missing,
118+
# it indicates this task was triggered by a non-BA upload.
119+
#
120+
# To prevent redundant caching of the same parent report:
121+
# 1. We first check if a BA report already exists for this commit
122+
# 2. We then verify there are uploads associated with it that aren't in an error state
123+
#
124+
# If both conditions are met, we can exit the task early since the caching was likely
125+
# already handled. Otherwise, we need to:
126+
# 1. Create a new BA report and upload
127+
# 2. Proceed with caching data from the parent report
128+
commit_report = (
129+
db_session.query(CommitReport)
130+
.filter_by(
131+
commit_id=commit.id,
132+
report_type=ReportType.BUNDLE_ANALYSIS.value,
133+
)
134+
.first()
135+
)
136+
if commit_report:
137+
upload_states = [upload.state for upload in commit_report.uploads]
138+
if upload_states and any(
139+
upload_state != "error" for upload_state in upload_states
140+
):
141+
log.info(
142+
"Bundle analysis report already exists for commit, skipping carryforward",
143+
extra=dict(
144+
repoid=commit.repoid,
145+
commit=commit.commitid,
146+
),
147+
)
148+
return processing_results
149+
else:
150+
# If the commit report does not exist, we will create a new one
151+
commit_report = report_service.initialize_and_save_report(commit)
152+
118153
upload = report_service.create_report_upload({"url": ""}, commit_report)
119154
carriedforward = True
120155

@@ -161,6 +196,17 @@ def process_impl_within_lock(
161196

162197
processing_results.append(result.as_dict())
163198
except (CeleryError, SoftTimeLimitExceeded, SQLAlchemyError):
199+
log.exception(
200+
"Unable to process bundle analysis upload",
201+
extra=dict(
202+
repoid=repoid,
203+
commit=commitid,
204+
commit_yaml=commit_yaml,
205+
params=params,
206+
upload_id=upload.id_,
207+
parent_task=self.request.parent_id,
208+
),
209+
)
164210
raise
165211
except Exception:
166212
log.exception(

tasks/tests/unit/test_bundle_analysis_processor_task.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,3 +1293,123 @@ def test_bundle_analysis_processor_task_no_upload(
12931293
assert commit.state == "complete"
12941294
assert upload.state == "processed"
12951295
assert upload.upload_type == "carriedforward"
1296+
1297+
1298+
@pytest.mark.django_db(databases={"default", "timeseries"})
1299+
def test_bundle_analysis_processor_task_carryforward(
1300+
mocker,
1301+
dbsession,
1302+
mock_storage,
1303+
):
1304+
storage_path = (
1305+
"v1/repos/testing/ed1bdd67-8fd2-4cdb-ac9e-39b99e4a3892/bundle_report.sqlite"
1306+
)
1307+
mock_storage.write_file(get_bucket_name(), storage_path, "test-content")
1308+
1309+
mocker.patch.object(
1310+
BundleAnalysisProcessorTask,
1311+
"app",
1312+
tasks={
1313+
bundle_analysis_save_measurements_task_name: mocker.MagicMock(),
1314+
},
1315+
)
1316+
1317+
commit = CommitFactory.create(state="pending")
1318+
dbsession.add(commit)
1319+
dbsession.flush()
1320+
1321+
commit_report = CommitReport(
1322+
commit_id=commit.id_, report_type=ReportType.BUNDLE_ANALYSIS.value
1323+
)
1324+
dbsession.add(commit_report)
1325+
dbsession.flush()
1326+
1327+
upload = UploadFactory.create(
1328+
storage_path=storage_path, report=commit_report, state="processed"
1329+
)
1330+
dbsession.add(upload)
1331+
dbsession.flush()
1332+
1333+
BundleAnalysisProcessorTask().run_impl(
1334+
dbsession,
1335+
{"results": [{"previous": "result"}]},
1336+
repoid=commit.repoid,
1337+
commitid=commit.commitid,
1338+
commit_yaml={},
1339+
params={
1340+
"upload_id": None,
1341+
"commit": commit.commitid,
1342+
},
1343+
)
1344+
1345+
# A new upload wasn't created because the caching was skipped
1346+
total_uploads = (
1347+
dbsession.query(Upload).filter_by(report_id=commit_report.id).count()
1348+
)
1349+
assert total_uploads == 1
1350+
1351+
# A new report wasn't created either
1352+
total_ba_reports = (
1353+
dbsession.query(CommitReport).filter_by(commit_id=commit.id).count()
1354+
)
1355+
assert total_ba_reports == 1
1356+
1357+
1358+
@pytest.mark.django_db(databases={"default", "timeseries"})
1359+
def test_bundle_analysis_processor_task_carryforward_error(
1360+
mocker,
1361+
dbsession,
1362+
mock_storage,
1363+
):
1364+
storage_path = (
1365+
"v1/repos/testing/ed1bdd67-8fd2-4cdb-ac9e-39b99e4a3892/bundle_report.sqlite"
1366+
)
1367+
mock_storage.write_file(get_bucket_name(), storage_path, "test-content")
1368+
1369+
mocker.patch.object(
1370+
BundleAnalysisProcessorTask,
1371+
"app",
1372+
tasks={
1373+
bundle_analysis_save_measurements_task_name: mocker.MagicMock(),
1374+
},
1375+
)
1376+
1377+
commit = CommitFactory.create(state="pending")
1378+
dbsession.add(commit)
1379+
dbsession.flush()
1380+
1381+
commit_report = CommitReport(
1382+
commit_id=commit.id_, report_type=ReportType.BUNDLE_ANALYSIS.value
1383+
)
1384+
dbsession.add(commit_report)
1385+
dbsession.flush()
1386+
1387+
upload = UploadFactory.create(
1388+
storage_path=storage_path, report=commit_report, state="error"
1389+
)
1390+
dbsession.add(upload)
1391+
dbsession.flush()
1392+
1393+
BundleAnalysisProcessorTask().run_impl(
1394+
dbsession,
1395+
{"results": [{"previous": "result"}]},
1396+
repoid=commit.repoid,
1397+
commitid=commit.commitid,
1398+
commit_yaml={},
1399+
params={
1400+
"upload_id": None,
1401+
"commit": commit.commitid,
1402+
},
1403+
)
1404+
1405+
# A new upload was created because all the previous uploads were in error states
1406+
total_uploads = (
1407+
dbsession.query(Upload).filter_by(report_id=commit_report.id).count()
1408+
)
1409+
assert total_uploads == 2
1410+
1411+
# There should still only be 1 BA report
1412+
total_ba_reports = (
1413+
dbsession.query(CommitReport).filter_by(commit_id=commit.id).count()
1414+
)
1415+
assert total_ba_reports == 1

0 commit comments

Comments
 (0)