Skip to content

Commit e4d7a82

Browse files
authored
Merge pull request #2946 from fedspendingtransparency/warmfix/transaction-search-deletes-qat
[Warmfix] Follows pattern for deleting stale fabs/fpds to also delete transaction_search
2 parents 6a06a49 + 13b5e0c commit e4d7a82

File tree

3 files changed

+31
-8
lines changed

3 files changed

+31
-8
lines changed

usaspending_api/broker/helpers/delete_stale_fabs.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@ def delete_stale_fabs(ids_to_delete):
3232
if delete_transaction_ids:
3333
fabs = 'DELETE FROM "transaction_fabs" tf WHERE tf."transaction_id" IN ({});'
3434
tn = 'DELETE FROM "transaction_normalized" tn WHERE tn."id" IN ({});'
35+
ts = 'DELETE FROM "transaction_search" ts WHERE ts."transaction_id" IN ({});'
3536
td = "DELETE FROM transaction_delta td WHERE td.transaction_id in ({});"
3637
queries.extend(
3738
[
3839
fabs.format(delete_transaction_str_ids),
3940
tn.format(delete_transaction_str_ids),
41+
ts.format(delete_transaction_str_ids),
4042
td.format(delete_transaction_str_ids),
4143
]
4244
)

usaspending_api/conftest.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66

77
from django.conf import settings
88
from django.core.management import call_command
9-
from django.db import connections, connection
9+
from django.db import connections
1010
from django.test import override_settings
1111
from pathlib import Path
1212

13+
from usaspending_api.common.helpers.sql_helpers import execute_sql_simple
1314
from usaspending_api.common.elasticsearch.elasticsearch_sql_helpers import (
1415
ensure_view_exists,
1516
ensure_business_categories_functions_exist,
@@ -46,14 +47,24 @@ def pytest_addoption(parser):
4647
def delete_tables_for_tests():
4748
"""
4849
Outside of testing, the transaction_search table is created by using a series of chunked matviews that are combined
49-
into a Django managed table. When unit testing transaction_search is created as a single matview. To prevent a
50+
into a Django managed table. When unit testing transaction_search is created as a single view. To prevent a
5051
naming conflict, the unused Django managed table is deleted while testing.
5152
"""
52-
with connection.cursor() as cursor:
53-
try:
54-
cursor.execute("DROP TABLE IF EXISTS transaction_search;")
55-
except Exception:
56-
pass
53+
try:
54+
execute_sql_simple("DROP TABLE IF EXISTS transaction_search;")
55+
except Exception:
56+
pass
57+
58+
59+
def add_view_protection():
60+
"""
61+
When unit testing transaction_search is created as a single view. Views can't be deleted from, so a custom rule
62+
is added to transaction_search to prevent sql errors when deletes are attempted
63+
"""
64+
try:
65+
execute_sql_simple("CREATE RULE ts_del_protect AS ON DELETE TO transaction_search DO INSTEAD NOTHING;")
66+
except Exception:
67+
pass
5768

5869

5970
@pytest.fixture(scope="session")
@@ -108,6 +119,7 @@ def django_db_setup(
108119
generate_matviews(materialized_views_as_traditional_views=True)
109120
ensure_view_exists(settings.ES_TRANSACTIONS_ETL_VIEW_NAME)
110121
ensure_view_exists(settings.ES_AWARDS_ETL_VIEW_NAME)
122+
add_view_protection()
111123
ensure_business_categories_functions_exist()
112124
call_command("load_broker_static_data")
113125

usaspending_api/etl/transaction_loaders/fpds_loader.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,23 @@ def delete_stale_fpds(detached_award_procurement_ids):
6868
cursor.execute(f"delete from transaction_fpds where transaction_id in ({txn_id_str}) returning transaction_id")
6969
deleted_fpds = set(cursor.fetchall())
7070

71+
cursor.execute(
72+
f"delete from transaction_search where transaction_id in ({txn_id_str}) returning transaction_id"
73+
)
74+
deleted_ts = set(cursor.fetchall())
75+
7176
cursor.execute(f"delete from transaction_normalized where id in ({txn_id_str}) returning id")
7277
deleted_transactions = set(cursor.fetchall())
7378

7479
if deleted_transactions != deleted_fpds:
7580
msg = "Delete Mismatch! Counts of transaction_normalized ({}) and transaction_fpds ({}) deletes"
7681
raise RuntimeError(msg.format(len(deleted_transactions), len(deleted_fpds)))
7782

78-
logger.info(f"{len(deleted_fpds):,} transactions deleted")
83+
if deleted_transactions != deleted_ts:
84+
msg = "Delete Mismatch! Counts of transaction_normalized ({}) and transaction_search ({}) deletes"
85+
raise RuntimeError(msg.format(len(deleted_transactions), len(deleted_ts)))
86+
87+
logger.info(f"{len(deleted_transactions):,} transactions deleted")
7988

8089
return awards_touched
8190

0 commit comments

Comments
 (0)