Skip to content

Commit 592d7ab

Browse files
Merge remote-tracking branch 'origin/master' into BFD-4348-prune-older-claim-versions-excluding-part-d
2 parents aaca2a9 + 19221ad commit 592d7ab

7 files changed

Lines changed: 132 additions & 90 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CREATE INDEX ON idr.claim_professional_ss(bfd_updated_ts) WHERE clm_type_cd BETWEEN 1000 and 1999;
2+
3+
CREATE INDEX ON idr.claim_institutional_ss(bfd_updated_ts) WHERE clm_type_cd BETWEEN 1000 and 1999;

apps/bfd-pipeline-idr/model/base_model.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
MIN_CLAIM_NCH_TRANSACTION_DATE,
4949
MIN_CLAIM_SS_TRANSACTION_DATE,
5050
MIN_PRIOR_AUTH_TRANSACTION_DATE,
51+
PHASE_1_PRUNE_BATCH_LIMIT,
5152
)
5253

5354
type DbType = str | float | int | bool | date | datetime
@@ -827,3 +828,26 @@ def claim_related_conditions_cte(source: Source) -> str:
827828
AND clm_rlt_cond_cd != '~'
828829
GROUP BY clm_rlt_cond_sgntr_sk
829830
"""
831+
832+
833+
def stale_phase_1_claims_query(
834+
header_table: str,
835+
item_table: str,
836+
cutoff_date: datetime,
837+
) -> tuple[str, tuple[datetime, datetime]]:
838+
return (
839+
f"""
840+
SELECT clm.clm_uniq_id
841+
FROM {header_table} clm
842+
WHERE clm.clm_type_cd BETWEEN {PHASE_1_SS_MIN} AND {PHASE_1_SS_MAX}
843+
AND clm.clm_src_id IN ('{FISS_CLM_SOURCE}', '{MCS_CLM_SOURCE}', '{VMS_CLM_SOURCE}')
844+
AND clm.bfd_updated_ts < %s
845+
AND NOT EXISTS (
846+
SELECT 1 FROM {item_table} item
847+
WHERE clm.clm_uniq_id = item.clm_uniq_id
848+
AND item.bfd_updated_ts >= %s
849+
)
850+
LIMIT {PHASE_1_PRUNE_BATCH_LIMIT}
851+
""",
852+
(cutoff_date, cutoff_date),
853+
)

apps/bfd-pipeline-idr/pipeline_stages.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@
3535
from model.idr_contract_pbp_number import IdrContractPbpNumber
3636
from model.idr_prior_auth import IdrPriorAuth
3737
from parallel_executor import ParallelStagesExecutor, Stage
38-
from pipeline_utils import extract_and_load, prune_bene_lis_cmbnd
39-
from pipeline_utils import extract_and_load, prune_phase_1_ss_claims
38+
from pipeline_utils import extract_and_load, prune_bene_lis_cmbnd, prune_phase_1_ss_claims
4039
from settings import enable_prior_auth_ingestion
4140

4241
type NodePartitionedModelInput = tuple[type[IdrBaseModel], LoadPartition | None]
@@ -48,7 +47,7 @@
4847
IdrClaimProfessionalSs,
4948
IdrClaimInstitutionalSs,
5049
]
51-
_CLAIM_SS_TABLES: list[type[IdrBaseModel]] = [
50+
CLAIM_SS_TABLES: list[type[IdrBaseModel]] = [
5251
IdrClaimProfessionalSs,
5352
IdrClaimInstitutionalSs,
5453
]
@@ -152,11 +151,7 @@ def _stage5_do_phase_1_prune(self) -> Stage[bool]:
152151
self.load_mode,
153152
)
154153

155-
def _stage5_do_phase_1_prune(self) -> Stage[bool]:
156-
if self.load_type == LoadType.INITIAL:
157-
return
158-
159-
for model in self._filter_tables(_CLAIM_SS_TABLES):
154+
for model in self._filter_tables(CLAIM_SS_TABLES):
160155
yield functools.partial(
161156
prune_phase_1_ss_claims,
162157
model,

apps/bfd-pipeline-idr/pipeline_utils.py

Lines changed: 20 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -9,33 +9,28 @@
99
from snowflake.connector.network import ReauthenticationRequest, RetryRequest
1010

1111
from batch_worker import LoadingBatchWorkerClient
12-
from constants import DEFAULT_MAX_DATE, DEFAULT_PARTITION
1312
from constants import (
1413
CLAIM_INSTITUTIONAL_ITEM_SS_TABLE,
1514
CLAIM_INSTITUTIONAL_SS_TABLE,
1615
CLAIM_PROFESSIONAL_ITEM_SS_TABLE,
1716
CLAIM_PROFESSIONAL_SS_TABLE,
17+
DEFAULT_MAX_DATE,
1818
DEFAULT_PARTITION,
19-
FISS_CLM_SOURCE,
2019
IDR_CLAIM_TABLE,
21-
MCS_CLM_SOURCE,
2220
PART_D_CLAIM_TYPE_CODES,
2321
PHASE_1_CUTOFF,
24-
PHASE_1_SS_MAX,
25-
PHASE_1_SS_MIN,
26-
VMS_CLM_SOURCE,
2722
)
2823
from extractor import PostgresExtractor, SnowflakeExtractor, Source
2924
from load_partition import LoadPartition
3025
from loader import LoadType, PostgresLoader, get_connection_string, should_track_load_progress
3126
from model.base_model import (
3227
LoadMode,
3328
T,
29+
stale_phase_1_claims_query,
3430
)
3531
from model.idr_beneficiary_low_income_subsidy_cmbnd import IdrBeneficiaryLowIncomeSubsidyCmbnd
3632
from model.load_progress import LoadProgress
37-
from settings import BENEFICIARY_PRUNE_BATCH_LIMIT
38-
from settings import PRUNE_BATCH_MAX_SIZE
33+
from settings import BENEFICIARY_PRUNE_BATCH_LIMIT, PRUNE_BATCH_MAX_SIZE
3934

4035

4136
def get_progress(
@@ -138,7 +133,7 @@ def _prune_table_in_batches(
138133
delete_query: str,
139134
params: tuple[Any, ...] | None = None,
140135
) -> None:
141-
# Run a batched DELETE until no matching rows remain.
136+
"""Run a batched DELETE until no matching rows remain."""
142137
total_rows_pruned = 0
143138

144139
while True:
@@ -174,50 +169,27 @@ def prune_phase_1_ss_claims(
174169
prune_cutoff_date = job_start - timedelta(days=PHASE_1_CUTOFF)
175170
part_d_codes = ",".join(str(code) for code in PART_D_CLAIM_TYPE_CODES)
176171

177-
phase_1_claim_filter = f"""
178-
clm.clm_type_cd BETWEEN {PHASE_1_SS_MIN} AND {PHASE_1_SS_MAX}
179-
AND clm.clm_src_id IN
180-
('{FISS_CLM_SOURCE}', '{MCS_CLM_SOURCE}', '{VMS_CLM_SOURCE}')
181-
AND clm.clm_idr_ld_dt < %s
182-
"""
183-
non_latest_non_part_d_claim_filter = f"""
184-
clm.clm_ltst_clm_ind = 'N'
185-
AND clm.clm_type_cd NOT IN ({part_d_codes})
186-
AND clm.clm_idr_ld_dt < %s
187-
"""
188-
189172
logger.info("pruning phase 1 ss claims older than {}", prune_cutoff_date)
190173

174+
prune_query, params = stale_phase_1_claims_query(claim_table, item_table, prune_cutoff_date)
175+
191176
with psycopg.connect(get_connection_string(load_mode)) as conn:
192-
_prune_table_in_batches(
193-
conn,
194-
item_table,
195-
f"""
196-
DELETE FROM {item_table}
197-
WHERE (clm_uniq_id, bfd_row_id) IN (
198-
SELECT item.clm_uniq_id, item.bfd_row_id
199-
FROM {item_table} item
200-
JOIN {claim_table} clm ON clm.clm_uniq_id = item.clm_uniq_id
201-
WHERE {phase_1_claim_filter}
202-
LIMIT {PRUNE_BATCH_MAX_SIZE}
203-
)
177+
for target_table in [item_table, claim_table]:
178+
_prune_table_in_batches(
179+
conn,
180+
target_table,
181+
f"""
182+
DELETE FROM {target_table}
183+
WHERE clm_uniq_id IN ({prune_query})
204184
""",
205-
(prune_cutoff_date,),
206-
)
185+
params,
186+
)
207187

208-
_prune_table_in_batches(
209-
conn,
210-
claim_table,
211-
f"""
212-
DELETE FROM {claim_table}
213-
WHERE clm_uniq_id IN (
214-
SELECT clm.clm_uniq_id FROM {claim_table} clm
215-
WHERE {phase_1_claim_filter}
216-
LIMIT {PRUNE_BATCH_MAX_SIZE}
217-
)
218-
""",
219-
(prune_cutoff_date,),
220-
)
188+
non_latest_non_part_d_claim_filter = f"""
189+
clm.clm_ltst_clm_ind = 'N'
190+
AND clm.clm_type_cd NOT IN ({part_d_codes})
191+
AND clm.clm_idr_ld_dt < %s
192+
"""
221193

222194
logger.info("pruning non-latest non-Part-D ss claims older than {}", prune_cutoff_date)
223195

apps/bfd-pipeline-idr/settings.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ def enable_prior_auth_ingestion() -> bool:
100100
"""Number of minimum connections to hold in the pool concurrently per-batch for non-LOCAL loads.
101101
Defaults to 20."""
102102

103+
PHASE_1_PRUNE_BATCH_LIMIT = int(getenv("PHASE_1_PRUNE_BATCH_LIMIT", "10_000"))
104+
"""The maximum batch size for pruning old claims (phase 1 claims from shared systems) on
105+
INCREMENTAL loads. Defaults to 10000."""
106+
103107
BENEFICIARY_PRUNE_BATCH_LIMIT = int(getenv("IDR_BENEFICIARY_PRUNE_BATCH_LIMIT", "1000"))
104108
"""Maximum rows to delete per prune statement for LIS combined beneficiary records."""
105109

apps/bfd-pipeline-idr/test_pipeline.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import shutil
33
import subprocess
44
from collections.abc import Generator
5-
from datetime import datetime, timedelta
5+
from datetime import UTC, datetime, timedelta
66
from pathlib import Path
77
from typing import cast
88
from uuid import uuid4
@@ -267,6 +267,32 @@ def _do_test_pipeline(conn: Connection[DictRow], load_type: LoadType) -> None:
267267

268268
conn.commit()
269269

270+
# Phase 1 SS (PAC) claims older than 60 days will be pruned on incremental loads
271+
if load_type == LoadType.INITIAL:
272+
cur = conn.execute("select * from idr.claim_institutional_ss order by clm_uniq_id")
273+
assert cur.rowcount == 21
274+
rows = cur.fetchmany(1)
275+
assert rows[0]["clm_uniq_id"] == 123359318723
276+
277+
cur = conn.execute("select * from idr.claim_item_institutional_ss order by clm_uniq_id")
278+
assert cur.rowcount == 328
279+
rows = cur.fetchmany(1)
280+
assert rows[0]["clm_uniq_id"] == 123359318723
281+
282+
else:
283+
make_it_stale_ts = datetime.now(UTC) + timedelta(days=60)
284+
_advance_time(make_it_stale_ts)
285+
run(Source.POSTGRES, LoadMode.SYNTHETIC, LoadType.INCREMENTAL)
286+
cur = conn.execute("select * from idr.claim_institutional_ss order by clm_uniq_id")
287+
assert cur.rowcount == 9
288+
rows = cur.fetchmany(1)
289+
assert rows[0]["clm_uniq_id"] == 849348853948
290+
291+
cur = conn.execute("select * from idr.claim_item_institutional_ss order by clm_uniq_id")
292+
assert cur.rowcount == 151
293+
rows = cur.fetchmany(1)
294+
assert rows[0]["clm_uniq_id"] == 849348853948
295+
270296
# Test incremental loading logic involving 'source_load_events' if we're testing incremental
271297
# mode
272298
if load_type == LoadType.INCREMENTAL:

insights/terraform/projects/bb2/services/analytics/modules/lambda/update_athena_metric_tables/sql_templates/template_generate_metrics_for_report_date.sql

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,41 +1515,59 @@ SELECT
15151515
)
15161516
) as auth_v3_user_makes_it_to_permission_screen_bene_count,
15171517
(
1518-
select
1519-
count(*)
1520-
from
1521-
api_audit_events
1522-
WHERE
1523-
(
1524-
CONTAINS((SELECT enabled_metrics_list FROM report_params),
1525-
'auth_v1_v2_user_clicks_connect_bene_count')
1526-
AND (
1527-
try_cast(crosswalk_fhir_id as BIGINT) > 0
1528-
OR COALESCE(try_cast(crosswalk_fhir_id_v3 as BIGINT), 0) > 0
1529-
)
1530-
AND type = 'Authorization'
1531-
AND
1532-
( path LIKE '/v1/o/authorize%'
1533-
OR path LIKE '/v2/o/authorize%'
1534-
)
1535-
)
1518+
SELECT COUNT(*)
1519+
FROM (
1520+
SELECT
1521+
path,
1522+
crosswalk_fhir_id_v3,
1523+
crosswalk_fhir_id
1524+
FROM
1525+
api_audit_events
1526+
WHERE
1527+
(
1528+
CONTAINS((SELECT enabled_metrics_list FROM report_params),
1529+
'auth_v1_v2_user_clicks_connect_bene_count')
1530+
AND (
1531+
try_cast(crosswalk_fhir_id as BIGINT) > 0
1532+
OR COALESCE(try_cast(crosswalk_fhir_id_v3 as BIGINT), 0) > 0
1533+
)
1534+
AND type = 'Authorization'
1535+
AND (
1536+
path LIKE '/v1/o/authorize%'
1537+
OR path LIKE '/v2/o/authorize%'
1538+
)
1539+
)
1540+
GROUP BY
1541+
path,
1542+
crosswalk_fhir_id_v3,
1543+
crosswalk_fhir_id
1544+
) AS grouped_results
15361545
) as auth_v1_v2_user_clicks_connect_bene_count,
15371546
(
1538-
select
1539-
count(*)
1540-
from
1541-
api_audit_events
1542-
WHERE
1543-
(
1544-
CONTAINS((SELECT enabled_metrics_list FROM report_params),
1545-
'auth_v3_user_clicks_connect_bene_count')
1546-
AND (
1547-
try_cast(crosswalk_fhir_id as BIGINT) > 0
1548-
OR COALESCE(try_cast(crosswalk_fhir_id_v3 as BIGINT), 0) > 0
1549-
)
1550-
AND type = 'Authorization'
1551-
AND path LIKE '/v3/o/authorize%'
1552-
)
1547+
SELECT COUNT(*)
1548+
FROM (
1549+
SELECT
1550+
path,
1551+
crosswalk_fhir_id_v3,
1552+
crosswalk_fhir_id
1553+
FROM
1554+
api_audit_events
1555+
WHERE
1556+
(
1557+
CONTAINS((SELECT enabled_metrics_list FROM report_params),
1558+
'auth_v3_user_clicks_connect_bene_count')
1559+
AND (
1560+
try_cast(crosswalk_fhir_id as BIGINT) > 0
1561+
OR COALESCE(try_cast(crosswalk_fhir_id_v3 as BIGINT), 0) > 0
1562+
)
1563+
AND type = 'Authorization'
1564+
AND path LIKE '/v3/o/authorize%'
1565+
)
1566+
GROUP BY
1567+
path,
1568+
crosswalk_fhir_id_v3,
1569+
crosswalk_fhir_id
1570+
) AS grouped_results
15531571
) as auth_v3_user_clicks_connect_bene_count,
15541572
(
15551573
select

0 commit comments

Comments
 (0)