Skip to content

Commit 6eccea6

Browse files
committed
ER Dose 서머리를 별도 DELETE·INSERT 메서드로 교체
1 parent 9bf2091 commit 6eccea6

6 files changed

Lines changed: 88 additions & 37 deletions

File tree

er_dose/euv/euv_processor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ def _run_window(
118118

119119
for target_date in sorted(inserted_target_dates):
120120
self.repository.analyze_target_partition(target_date, connection=connection)
121-
self.repository.upsert_root_cause_daily_summary(target_date, connection=connection)
121+
self.repository.replace_root_cause_daily_summary(target_date)
122122
print(
123123
"[ER_DOSE_EUV] "
124124
f"summary updated (root_cause) partition_date={target_date}"

er_dose/euv/euv_repository.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,25 @@ def analyze_target_partition(self, target_date: str, connection=None) -> int:
224224
partition_table = f"{ROOT_CAUSE_TABLE}_1_prt_p{target_date.replace('-', '')}"
225225
return self.db.execute(f"ANALYZE {partition_table}", connection=connection)
226226

227-
def upsert_root_cause_daily_summary(self, target_date: date | str, connection=None) -> int:
227+
def replace_root_cause_daily_summary(self, target_date: date | str) -> None:
228+
self.delete_root_cause_daily_summary(target_date)
229+
self.insert_root_cause_daily_summary(target_date)
230+
231+
def delete_root_cause_daily_summary(self, target_date: date | str) -> None:
232+
if isinstance(target_date, str):
233+
target_date = datetime.strptime(target_date, "%Y-%m-%d").date()
234+
delete_query = """
235+
delete from prism_common.de_trend_root_cause_daily
236+
where occur_date = :target_date
237+
"""
238+
self.db.execute(delete_query, params={"target_date": target_date})
239+
240+
def insert_root_cause_daily_summary(self, target_date: date | str) -> None:
228241
if isinstance(target_date, str):
229242
target_date = datetime.strptime(target_date, "%Y-%m-%d").date()
230243
start_time = datetime.combine(target_date, datetime.min.time())
231244
end_time = start_time + timedelta(days=1)
232-
233-
query = f"""
245+
insert_query = f"""
234246
insert into prism_common.de_trend_root_cause_daily (
235247
occur_date,
236248
eq_name,
@@ -274,13 +286,9 @@ def upsert_root_cause_daily_summary(self, target_date: date | str, connection=No
274286
from root_cause_data
275287
where root_cause is not null
276288
and root_cause != ''
277-
group by occur_date, eq_name, root_cause
278-
on conflict (occur_date, eq_name, root_cause)
279-
do update set
280-
frequency = excluded.frequency,
281-
created_at = now();
289+
group by occur_date, eq_name, root_cause;
282290
"""
283-
return self.db.execute(query, params={"start_time": start_time, "end_time": end_time}, connection=connection)
291+
self.db.execute(insert_query, params={"start_time": start_time, "end_time": end_time})
284292

285293
def transaction(self):
286294
return self.db.transaction()

er_dose/raw/raw_processor.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,8 @@ def _run_window(
165165

166166
for target_date in sorted(inserted_target_dates):
167167
self.repository.analyze_target_partition(target_date, connection=connection)
168-
self.repository.upsert_die_yield_daily_summary(target_date, connection=connection)
169-
self.repository.upsert_root_cause_daily_summary(target_date, connection=connection)
168+
self.repository.replace_die_yield_daily_summary(target_date)
169+
self.repository.replace_root_cause_daily_summary(target_date)
170170
print(
171171
"[ER_DOSE] "
172172
f"summary updated (die_yield, root_cause) partition_date={target_date}"
@@ -385,7 +385,7 @@ def _run_window(
385385

386386
for target_date in sorted(inserted_target_dates):
387387
self.repository.analyze_target_partition(target_date, connection=connection)
388-
self.repository.upsert_root_cause_daily_summary(target_date, connection=connection)
388+
self.repository.replace_root_cause_daily_summary(target_date)
389389
print(
390390
"[ER_DOSE_EUV] "
391391
f"summary updated (root_cause) partition_date={target_date}"

er_dose/raw/raw_repository.py

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -232,13 +232,25 @@ def analyze_target_partition(self, target_date: str, connection=None) -> int:
232232
partition_table = f"{PARSED_TABLE}_1_prt_p{target_date.replace('-', '')}"
233233
return self.db.execute(f"ANALYZE {partition_table}", connection=connection)
234234

235-
def upsert_die_yield_daily_summary(self, target_date: date | str, connection=None) -> int:
235+
def replace_die_yield_daily_summary(self, target_date: date | str) -> None:
236+
self.delete_die_yield_daily_summary(target_date)
237+
self.insert_die_yield_daily_summary(target_date)
238+
239+
def delete_die_yield_daily_summary(self, target_date: date | str) -> None:
240+
if isinstance(target_date, str):
241+
target_date = datetime.strptime(target_date, "%Y-%m-%d").date()
242+
delete_query = """
243+
delete from prism_common.de_trend_die_yield_daily
244+
where occur_date = :target_date
245+
"""
246+
self.db.execute(delete_query, params={"target_date": target_date})
247+
248+
def insert_die_yield_daily_summary(self, target_date: date | str) -> None:
236249
if isinstance(target_date, str):
237250
target_date = datetime.strptime(target_date, "%Y-%m-%d").date()
238251
start_time = datetime.combine(target_date, datetime.min.time())
239252
end_time = start_time + timedelta(days=1)
240-
241-
query = f"""
253+
insert_query = f"""
242254
insert into prism_common.de_trend_die_yield_daily (
243255
occur_date,
244256
eq_name,
@@ -307,26 +319,29 @@ def upsert_die_yield_daily_summary(self, target_date: date | str, connection=Non
307319
sum(case when valid_wafer_yn = 1 then reject_yn else 0 end) as reject_wafer,
308320
now() as created_at
309321
from wafer_code_data
310-
group by occur_date, eq_name
311-
on conflict (occur_date, eq_name)
312-
do update set
313-
total_die = excluded.total_die,
314-
reject_shot = excluded.reject_shot,
315-
to_repair_die = excluded.to_repair_die,
316-
repair_nok = excluded.repair_nok,
317-
total_wafer = excluded.total_wafer,
318-
reject_wafer = excluded.reject_wafer,
319-
created_at = now();
322+
group by occur_date, eq_name;
320323
"""
321-
return self.db.execute(query, params={"start_time": start_time, "end_time": end_time}, connection=connection)
324+
self.db.execute(insert_query, params={"start_time": start_time, "end_time": end_time})
322325

323-
def upsert_root_cause_daily_summary(self, target_date: date | str, connection=None) -> int:
326+
def replace_root_cause_daily_summary(self, target_date: date | str) -> None:
327+
self.delete_root_cause_daily_summary(target_date)
328+
self.insert_root_cause_daily_summary(target_date)
329+
330+
def delete_root_cause_daily_summary(self, target_date: date | str) -> None:
331+
if isinstance(target_date, str):
332+
target_date = datetime.strptime(target_date, "%Y-%m-%d").date()
333+
delete_query = """
334+
delete from prism_common.de_trend_root_cause_daily
335+
where occur_date = :target_date
336+
"""
337+
self.db.execute(delete_query, params={"target_date": target_date})
338+
339+
def insert_root_cause_daily_summary(self, target_date: date | str) -> None:
324340
if isinstance(target_date, str):
325341
target_date = datetime.strptime(target_date, "%Y-%m-%d").date()
326342
start_time = datetime.combine(target_date, datetime.min.time())
327343
end_time = start_time + timedelta(days=1)
328-
329-
query = """
344+
insert_query = """
330345
insert into prism_common.de_trend_root_cause_daily (
331346
occur_date,
332347
eq_name,
@@ -345,13 +360,9 @@ def upsert_root_cause_daily_summary(self, target_date: date | str, connection=No
345360
and p.code_occur_time < :end_time
346361
and p.eq_name is not null
347362
and p.root_cause is not null
348-
group by p.code_occur_time::date, p.eq_name, p.root_cause
349-
on conflict (occur_date, eq_name, root_cause)
350-
do update set
351-
frequency = excluded.frequency,
352-
created_at = now();
363+
group by p.code_occur_time::date, p.eq_name, p.root_cause;
353364
"""
354-
return self.db.execute(query, params={"start_time": start_time, "end_time": end_time}, connection=connection)
365+
self.db.execute(insert_query, params={"start_time": start_time, "end_time": end_time})
355366

356367
def transaction(self):
357368
return self.db.transaction()

tests/test_er_dose_processor.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,10 @@ def test_run_inserts_rows_without_deleting_existing_history(self):
282282
with redirect_stdout(StringIO()):
283283
processor.run(start_time=datetime(2026, 5, 1), end_time=datetime(2026, 5, 2))
284284

285-
delete_queries = [query for query, _, _ in db.executed if query.strip().lower().startswith("delete")]
285+
delete_queries = [
286+
query for query, _, _ in db.executed
287+
if query.strip().lower().startswith("delete") and "er_dose_raw_parsed" in query.lower()
288+
]
286289
self.assertEqual(delete_queries, [])
287290
parsed_insert = self._inserted_df(db, "prism_common.er_dose_raw_parsed")
288291
self.assertNotIn("parser_version", parsed_insert.columns)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from datetime import date
2+
from unittest.mock import Mock
3+
import pytest
4+
from er_dose.raw.raw_repository import ERDoseRepository
5+
from er_dose.euv.euv_repository import ERDoseEUVRepository
6+
7+
@pytest.mark.parametrize("repository_type,kind", [(ERDoseRepository,"die_yield"),(ERDoseRepository,"root_cause"),(ERDoseEUVRepository,"root_cause")])
8+
@pytest.mark.parametrize("failure", [None,"delete","insert"])
9+
def test_summary_uses_separate_statements(repository_type, kind, failure):
10+
db = Mock()
11+
events = []
12+
def execute(query, params):
13+
action = query.strip().split()[0].lower()
14+
events.append(action)
15+
if action == failure:
16+
raise RuntimeError(action)
17+
db.execute.side_effect = execute
18+
repo = repository_type(db)
19+
method = getattr(repo, 'replace_' + kind + '_daily_summary')
20+
if failure:
21+
with pytest.raises(RuntimeError, match=failure):
22+
method(date(2026,5,1))
23+
else:
24+
assert method(date(2026,5,1)) is None
25+
assert events == (['delete'] if failure == 'delete' else ['delete','insert'])
26+
db.transaction.assert_not_called()
27+
for call in db.execute.call_args_list:
28+
assert 'connection' not in call.kwargs
29+
assert 'on conflict' not in call.args[0].lower()

0 commit comments

Comments
 (0)