fix: drift_monitor.py 정시읽기 절전 모드 대응 및 예외 안정성 개선
- services/drift_monitor.py - threading.Timer 체인 방식 → 폴링 루프 스레드로 교체 - 30초 간격 폴링으로 절전 복귀 시 즉시 감지 - _do_read()를 try/except로 감싸 예외 시에도 루프 유지 - threading.Event로 깔끔한 중지 처리 - _schedule_hourly(), _hourly_tick() 삭제 → _hourly_loop() 신규 - Dabit Time Manager.spec - 빌드 출력 파일명 v1.0 → v1.1 업데이트 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,7 +16,8 @@ class DriftMonitor:
|
||||
|
||||
def __init__(self):
|
||||
self._timer: threading.Timer | None = None
|
||||
self._hourly_timer: threading.Timer | None = None
|
||||
self._hourly_thread: threading.Thread | None = None
|
||||
self._hourly_stop_event: threading.Event | None = None
|
||||
self._running = False
|
||||
self._hourly_running = False
|
||||
self._interval = DEFAULT_MONITOR_INTERVAL
|
||||
@@ -72,36 +73,49 @@ class DriftMonitor:
|
||||
if self._hourly_running:
|
||||
return
|
||||
self._hourly_running = True
|
||||
self._schedule_hourly()
|
||||
self._hourly_stop_event = threading.Event()
|
||||
self._hourly_thread = threading.Thread(target=self._hourly_loop, daemon=True)
|
||||
self._hourly_thread.start()
|
||||
|
||||
def stop_hourly(self):
|
||||
"""매시 정시 읽기 중지."""
|
||||
self._hourly_running = False
|
||||
if self._hourly_timer:
|
||||
self._hourly_timer.cancel()
|
||||
self._hourly_timer = None
|
||||
if self._hourly_stop_event:
|
||||
self._hourly_stop_event.set()
|
||||
self._hourly_thread = None
|
||||
|
||||
def _schedule_hourly(self):
|
||||
"""다음 정시까지 대기 후 읽기 예약."""
|
||||
if not self._hourly_running:
|
||||
return
|
||||
now = datetime.now()
|
||||
# 다음 정시: 현재 시 + 1, 분/초 = 0
|
||||
next_hour = now.replace(minute=0, second=0, microsecond=0)
|
||||
next_hour = next_hour + timedelta(hours=1)
|
||||
delay = (next_hour - now).total_seconds()
|
||||
if self._on_error:
|
||||
self._on_error(f"정시 읽기 예약: {next_hour.strftime('%H:%M:%S')} ({delay:.0f}초 후)")
|
||||
self._hourly_timer = threading.Timer(delay, self._hourly_tick)
|
||||
self._hourly_timer.daemon = True
|
||||
self._hourly_timer.start()
|
||||
def _hourly_loop(self):
|
||||
"""매시 정시 읽기 루프 (절전 복귀 대응)."""
|
||||
while self._hourly_running:
|
||||
now = datetime.now()
|
||||
next_hour = now.replace(minute=0, second=0, microsecond=0) + timedelta(hours=1)
|
||||
|
||||
def _hourly_tick(self):
|
||||
"""정시 도달 시 읽기 실행 후 다음 정시 예약."""
|
||||
if not self._hourly_running:
|
||||
return
|
||||
self._do_read(schedule_next=False)
|
||||
self._schedule_hourly()
|
||||
if self._on_error:
|
||||
delay = (next_hour - now).total_seconds()
|
||||
self._on_error(f"정시 읽기 예약: {next_hour.strftime('%H:%M:%S')} ({delay:.0f}초 후)")
|
||||
|
||||
# 30초 간격 폴링으로 정시 대기 (절전 복귀 시 즉시 감지)
|
||||
while self._hourly_running:
|
||||
now = datetime.now()
|
||||
if now >= next_hour:
|
||||
break
|
||||
remaining = (next_hour - now).total_seconds()
|
||||
wait = min(remaining, 30)
|
||||
if self._hourly_stop_event.wait(timeout=wait):
|
||||
return # 중지 요청
|
||||
|
||||
if not self._hourly_running:
|
||||
break
|
||||
|
||||
# 정시 읽기 실행
|
||||
try:
|
||||
self._do_read(schedule_next=False)
|
||||
except Exception as e:
|
||||
if self._on_error:
|
||||
try:
|
||||
self._on_error(f"정시 읽기 오류: {e}")
|
||||
except:
|
||||
pass
|
||||
|
||||
def read_once(self):
|
||||
"""즉시 한 번 읽기 (별도 스레드)."""
|
||||
|
||||
Reference in New Issue
Block a user