Files
trex-core/docs/batches/bat-018_20260608_trading-date-timezone-daily-preallocation/design.md
T
genichinandClaude Opus 4.8 0b7db66463 feat(runtime): dcy-014 trading_date KST 타임존 분리 + 일일 슬롯 preallocation (BAT-018)
데몬이 시스템 UTC 날짜로 슬롯을 1회만 preallocate 해 trading_date 가 KST 캘린더와
어긋나고 재시작 없이는 다음날 슬롯이 안 생기던 문제(issue #14) 정정.

거버넌스: 전부 change-req (신규 REQ 없음, dcy-014 OQ-3; 스케줄러는 REQ-030 패턴 준용).
- REQ-005: trading_date 를 설정 타임존(기본 Asia/Seoul) 기준 계산(timestamp 는 UTC
  유지). DailyPreallocationScheduler 신규 — TZ 일자당 1회 멱등 fire, 재시작 없이
  다음날 슬롯 자동 생성. setup() 배선 + trex-preallocation 스레드
- REQ-048: TOML trading_timezone/daily_preallocation_time 키 + from_config 전파
- REQ-009: runtime-flows/data-model 정합 + instance.example.toml

OQ-1 기본 00:00(TZ 자정, TOML 설정 가능) / OQ-2 매 캘린더일 생성(거래일 캘린더 후속).
멱등 preallocate 로 중복 tick·다중 인스턴스 중복 생성 0.

검증: 단위 302 passed/32 skipped, 인프라 게이트(PG+RabbitMQ) 334 passed, ruff clean.
신규 test_preallocation_scheduler(고정 clock) + test_instance_config 확장.
BAT-018 release-candidate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 15:39:04 +09:00

3.5 KiB

BAT-018 Design

  • Status: confirmed
  • Batch: BAT-018

설계 목표

  • trading_date 를 설정 타임존(기본 KST) 기준으로 분리해 KST 캘린더 일자와 DB 일자를 일치시키고, 재시작 없이 일자 경계마다 다음날 슬롯을 자동 생성한다(issue #14). timestamp 는 UTC 유지(NFR-1).

1. DailyPreallocationScheduler (REQ-005, REQ-030 패턴)

  • application/preallocation_scheduler.py(신규). 의존: slot_service(preallocate_daily_slots), total_slots, tz(tzinfo), schedule_time(time, 기본 00:00), clock(주입식, 기본 utcnow).
  • run_once(): trading_date = clock().astimezone(tz).date() → preallocate_daily_slots(trading_date, total_slots)(멱등) → _last_fired_date = trading_date. 반환 trading_date.
  • _maybe_tick(): now_tz = clock().astimezone(tz); target = combine(now_tz.date(), schedule_time, tz); now_tz < target 면 skip; _last_fired_date == now_tz.date() 면 skip(오늘 이미 생성); 아니면 run_once.
  • run_forever(stop, tick_sec=60): boot run_once(당일 즉시 확보) 후 stop.wait(tick_sec) 루프 + try/except(루프 생존).
  • 경계 의미: boot 는 항상 현재 TZ 일자 슬롯 확보(시각 무관). schedule_time 은 다음날 경계 fire 시점 게이트. 기본 00:00 → 자정 직후 다음날 생성.

2. 도메인 무침범 (A-3)

  • SlotService.preallocate_daily_slots(trading_date: date, count) 시그니처/멱등 그대로 재사용. TZ 계산은 스케줄러(호출부)에서만 수행 → REQ-002 도메인 본문 변경 없음.

3. 설정 (REQ-048, TOML 일원화)

  • DaemonInstanceConfig(TOML, frozen): trading_timezone: str = "Asia/Seoul", daily_preallocation_time: str = "00:00". from_toml 이 optional 키 파싱(부재 시 기본).
  • DaemonConfig: 동일 두 필드(기본 KST/00:00). from_env 는 기본값 사용(TOML 일원화 — env var 미도입). from_config 가 TOML 값으로 replace.
  • 운영자는 --config TOML 로 명시 지정(FR-4). 신규 설정 표면 아님.

4. daemon 배선 (REQ-005)

  • __init__: DailyPreallocationScheduler(slot_service, total_slots, tz=ZoneInfo(config.trading_timezone), schedule_time=_parse_kst_time(config.daily_preallocation_time)).
  • setup(): UTC 날짜 preallocate_daily_slots 직접 호출 제거 → preallocation_scheduler.run_once()(boot, TZ 당일 확보).
  • _preallocation_loop: run_forever(stop, tick_sec=60). workers 에 trex-preallocation 추가(8 스레드).

5. timestamp UTC 유지 (NFR-1)

  • 슬롯 created_at/updated_at/전이 ts 는 기존대로 datetime.now(tz=timezone.utc). 본 변경은 trading_date(date) 계산만 TZ 화.

6. baseline 문서 (REQ-009)

  • runtime-flows: 데몬 lifecycle(TOML 키 추가·8 스레드·setup preallocation_scheduler) + 일일 슬롯 preallocation Flow 신규.
  • data-model: trading_date=설정 TZ 기준 / timestamp=UTC 구분.
  • config/instance.example.toml: 두 키 주석 문서화.

멱등성/안정성 (NFR-2/3)

  • 일자당 1회 fire + preallocate date 멱등 → 중복 tick·다중 인스턴스 중복 생성 0. 재시작 시 boot run_once 가 당일 확보. 무재시작 일자 경계는 _maybe_tick 가 다음날 생성.

테스트 설계

  • tests/application/test_preallocation_scheduler.py(고정 clock 주입): KST/UTC 자정 경계 trading_date(S-1), timestamp UTC 유지(S-2), 일자 경계 자동 생성+멱등 재tick(S-3), 설정 TZ 변경(S-4), 트리거 시각 게이팅, idle 슬롯.
  • tests/runtime/test_instance_config.py 확장: TOML 기본값(KST/00:00) + TOML 값 from_config 전파.